Upstart is a lending technology platform. It uses machine learning models to assess risk so that bank partners can offer credit to consumers. Software Engineers write the backend services, APIs and user-facing applications behind that platform. Reported team alignments include the Partner Integrations and Origination Platform, the Capital Marketplace, the Distribution Platform, Cash Line and Pricing.
According to candidate reports, the work centers on high-throughput transaction processing, database consistency and integrations with external bank partners. The languages mentioned include Java, Ruby and JavaScript/TypeScript with React. Ruby on Rails, Sinatra and ActiveRecord come up as frameworks you may run into. Reported responsibilities also include code review, on-call rotations, production debugging and query or latency tuning. Senior and principal engineers also own service boundaries and technical direction.
In the interview, that background shows up as three kinds of preparation. The first is fast, readable solutions to practical coding problems under strict per-question time limits. The second is building and debugging a small working application in your own environment during the Project round. The third is design answers that deal directly with API contracts, schemas and the choice between strong and eventual consistency for financial data. Candidates report hiring across L4, L5/Senior and Principal levels, and design and leadership depth are expected to grow with seniority.
Recruiter Screen
reportedA recruiter conversation about your background and fit for the role. Use it to collect the facts that shape the rest of your preparation. Ask which team or platform the opening sits on, which level the loop is calibrated to (candidates report L4, L5/Senior and Principal), which platform the online assessment runs on, and what language and framework expectations apply to the Project round. Also confirm the location and hybrid expectations for the role on this call.
What to demonstrate
- Whether you can give a short, specific account of your background and why this company and role make sense for you
- Whether the scope you describe lines up with the level the role is hiring for
- Whether you have a considered answer when compensation expectations come up
How to prepare
- Rehearse a professional introduction and a 'why this company and role' answer that refers to the lending platform and the team area you are interviewing for, not generic fintech enthusiasm
- Prepare a compensation range with the components named, so a question about expectations gets a clear answer
- Write down your questions in advance: target team, level, assessment platform, Project-round language/framework and location expectations
- Pick the one project you will lead with later in the technical screen, and be able to summarize it in two sentences here
Online Technical Assessment
reportedCandidates describe this as a timed set of coding challenges on a platform such as CodeSignal or CoderPad, with strict time limits for each question. The coding problems in the question bank for this role make good practice for this format, and they are mostly practical: string rewriting (replacing punctuation, grouping strings), array filtering and reordering, de-duplication that keeps first-appearance order, bounding boxes over coordinates, and billing or revenue simulations. Because each question has its own time limit, a correct brute-force solution that finishes is worth more than an optimal one left half-written.
What to demonstrate
- Whether each solution returns the right output for the stated examples and for the edge cases they leave out
- Whether you finish the core logic within each question's limit before trying to optimize
- Whether the code is readable enough to follow at a glance
How to prepare
- Work through the bank's short problems (Filter Odds and Reverse Evens, String Replace and Grouping, Remove Duplicates While Preserving First-Appearance Order, Count Numbers Whose Successor Exists, Bounding Box From Coordinates) with a per-question timer you do not extend
- For simulation-style problems such as the buffet revenue and cafeteria billing tasks, list the state variables and the order of events before writing code
- Test against empty, single-element and duplicate-heavy inputs on every problem, since the prompt examples rarely cover them
- If you run short on time, write the remaining approach as comments so the intent is visible
Technical Screen
reportedCandidates report a session with a hiring manager or senior engineer. It combines a deep-dive into a past project with live coding, and sometimes system design. For the live-coding part, the reported coding questions for this role are useful practice because they turn on picking the right data structure: a custom stack that supports push, pop and a calculation over its elements, rolling statistics over a transaction stream using a map, and character-code differences between two long strings. Talk through your reasoning, write clean code and dry-run it against test cases.
What to demonstrate
- Whether you can explain the trade-offs in a project you drove, including what you chose not to do
- Whether you choose maps, sets or stacks to match the access pattern, and can state the resulting time and space complexity
- Whether you talk through your approach and dry-run the code before calling it finished
How to prepare
- Prepare one project walkthrough covering the problem, your design decisions, the alternatives you rejected, what broke and what you measured
- Practice the custom-stack pattern: store the aggregate-so-far with each element so push, pop and the query run in O(1). This works for min, max, sum, and mode with a count map (pop decrements the count and restores the stored mode). Median cannot be kept this way because it needs order statistics such as two heaps, so ask which calculation is meant before promising O(1)
- Practice a rolling-statistics problem over a keyed stream with a map of running aggregates, and state what happens when a key disappears
- Narrate brute force first, then the improvement, then trace one small input by hand before running anything
Virtual Onsite
reportedCandidates describe a virtual onsite made up of several distinct interviews. It covers live algorithmic coding, system design, a practical Project round, a values-based behavioral interview and a final conversation with a hiring manager or engineering leader. In the Project round you build or extend a working application in your own local environment while sharing your screen. Examples include a React front end or a lightweight Sinatra or Rails back end, with database migrations and model relationships. For the system design interview, practice the reported design questions for this role: a multiplayer chess game, an asynchronous loan-decision API for bank partners, rate limiting for distribution APIs, a high-volume ledger schema and a notifications service with at-least-once delivery.
What to demonstrate
- In the Project round, whether you finish with a working feature, including persistence, validation and error handling, inside your own environment
- In system design, whether you ask about business requirements, data volume and consistency guarantees before drawing the architecture
- In the values interview, whether your stories show ownership, handling of ambiguity and constructive disagreement with specific actions
- Whether your coding stays clear and tested even after earlier rounds the same day
How to prepare
- Before the day, have a boilerplate app in your chosen stack connected to a local database (PostgreSQL or SQLite), with one migration and one model relationship already tested end to end
- Rehearse building a small task-manager API with persistence against a short spec, then add input validation and error responses to it
- For every design question you practice, say where you need strong consistency (ledger balances, loan decisions) and where eventual consistency is acceptable (reporting, notification status)
- Prepare STAR stories for ownership, a production mistake, a tight deadline and a disagreement with product about technical debt
12 candidate reports. Individual accounts describe a particular role and hiring cycle.
Upstart Data Scientist interview: fast-paced statistics and probability questions
After the recruiter screen, I was told the hiring-manager interview would be a straightforward conversation with one technical question at the end. Instead, brief introductions led into deep theoretical statistics and difficult mental math. The interviewer moved extremely fast. When I was unsure or interpreted something differently, I didn't feel I received enough clarification to get back on tra…
Read full experienceUpstart Senior+ Data Scientist Interview Experience — Two Interviews Years Apart, Same Clash With the Interviewer
I applied to this company years ago, right after graduation, and it felt like neither I nor the phone-screen interviewer were really into each other. Fast forward many years, and this time the HR screen and phone screen actually went well at first — but the virtual onsite took me right back to those days. I ran into another interviewer where, again, neither of us was really into the other. That s…
Read full experienceUpstart Software Engineer Interview Experience — Six OA Questions Buried in Walls of Text
Very easy, 6 questions. The biggest challenge was that most of the questions were way too long — it took more than 2 minutes just to read and understand each one, and if you didn't pass on the first try, debugging got really stressful. For example, the first question (8 minute time limit) opened with a long paragraph about someone in medieval times who wrote a manuscript... two minutes later... t…
Read full experienceUpstart Software Engineer Interview Experience — Three OA Questions, Stuck on a Grid-Search Timeout
There were three questions in total, and two of them hadn't shown up in any interview reports before. Given a list of coordinates (x, y), find the min x, min y, max_x - min_x, and max_y - min_y. The problem statement was basically: filter out (name, score) pairs where the score is above a threshold, keep everything below the threshold, then find the max score among what's left and return its name…
Read full experienceUpstart Online Assessment Interview Experience — Byte Formatter and a Restaurant Capacity Simulation
View report detailsPracHub editorial advice for the preparation topics above.
Arriving at the Project round with a local environment that has never run a migration end to end
Time spent on database connection errors, package-manager mismatches or a boilerplate that does not boot comes straight out of your building time. A few days before, create the app in the stack you will use, connect it to a local database, run a migration, add one model with a relationship and hit one endpoint. Then restart your machine and repeat it from a cold start so you know it works on interview day.
Breaking model relationships with a naming or namespace mistake in Rails/ActiveRecord
Candidates report debugging a broken migration or model relationship, and a namespacing mistake in ActiveRecord can quietly break associations. If you use Rails, check table names, foreign keys and class_name/namespace settings as you create each model, and confirm each association in a console before building on it. If you use another stack, practice the same habit with its ORM.
Chasing the optimal solution on a timed assessment question and submitting nothing that passes
The online assessment has a separate time limit for each question. Write the simplest correct version first, run it against the examples plus an empty and a single-element input, and only then improve it. Most of the bank's short coding problems (filtering, string rewriting, de-duplication, bounding boxes) have a direct linear solution, so a long search for something clever usually means you misread the prompt.
Designing the ledger or loan-decision system without stating its consistency model
The reported design questions include a high-volume ledger schema and an asynchronous loan-decision API for bank partners. Say early which writes need ACID guarantees (balance changes, a decision recorded once), and which reads can be eventually consistent (dashboards, notification status). Then show how the schema and API enforce that: unique keys, idempotent retries and an explicit state for a partner decision that is still pending.
Describing a past project in the technical screen without the trade-offs
A walkthrough that lists technologies and team size tells the interviewer little about your judgment. For the project you lead with, prepare the two or three decisions that mattered, the alternative you rejected for each and why, and one thing that went wrong in production and how you handled it. A reported behavioral question asks directly for the most technically complex project you drove and its trade-offs.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Implement a custom stack data structure that supports push, pop, and a…
Implement a custom stack data structure that supports push, pop, and an arbitrary calculation over the elements in optimal time complexity.
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Walk one small example through your approach before writing the whole thing.
- Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
- What is the worst case, and how likely is it on real data?
- How does this change if the input no longer fits in memory?
Solve a mathematical word problem in code, optimizing for both time co…
Solve a mathematical word problem in code, optimizing for both time complexity and readability.
Approach
- Walk one small example through your approach before writing the whole thing.
- Choose the data structure from the access pattern, not from familiarity.
- Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
- Which test case would catch an off-by-one here?
- What is the worst case, and how likely is it on real data?
Given a list of integers and target constraints, find all unique combi…
Given a list of integers and target constraints, find all unique combinations that satisfy a specific mathematical formula.
Approach
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
- Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
- Which test case would catch an off-by-one here?
- How does this change if the input no longer fits in memory?
Write a function to find the character code differences between two lo…
Write a function to find the character code differences between two long strings.
Approach
- Walk one small example through your approach before writing the whole thing.
- Restate the input: its shape, its size, and what is guaranteed about it.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- What is the worst case, and how likely is it on real data?
- Which test case would catch an off-by-one here?
Detect duplicate-charge bursts in an out-of-order authorisation stream
Authorisations arrive as (instrument_token_id, amount_minor, currency, event_time, arrival_time) at roughly 3,000 per second, up to 60 seconds late and out of order. Flag any token with three or more authorisations of identical (amount_minor, currency) inside any 10-minute window of event time. Report each flag once, as early as correctness allows. State memory per key and in total, how late an event you will accept, and what you do with one that arrives after you have already reported — or already declined to report — that window.
Approach
- Key state by
(instrument_token_id, amount_minor, currency), not by token: the predicate is about identical amounts, so the window belongs to the triple. Each key holds its own event-time-ordered deque. - In-order, this is two pointers: on insert, pop from the front while
front <= new - 10 min, then flag if the deque reaches length 3. Amortised O(1) per event, memory proportional to that key's window occupancy. - Out-of-order arrival breaks append-only monotonicity, so insert in position instead. With lateness bounded at 60 seconds the insertion point is always near the tail, so a short sorted vector or a 600-bucket per-second ring keeps it O(w) with tiny w; a balanced tree per key is correct but over-built for a one-minute reorder.
- Drive decisions off a watermark of
max(event_time seen) - 60 s, never off wall clock. Anything older than the watermark is too late to change an answer and is counted in alate_droppedmetric. Without an explicit watermark you have still chosen a lateness policy — you just cannot state it or test it. - Report-once needs its own state: per key, a set of already-flagged 10-minute window ids. A later event inside an already-flagged window must not re-flag, and a late event that completes a window you never flagged must flag — which is why state is retired at window close plus the lateness bound, not at window close.
- Size it: state lives 660 seconds, so at 3,000 events per second there are about 1.98 million in flight, plus one flagged-window set per active key. Bound total memory explicitly and shed by key age, and say what shedding costs — a shed key can miss a flag, making the threshold a product decision rather than a tuning knob.
Worked solution 40 min
- Write the key, the window, the watermark and the report-once rule in four lines before any code; every later bug is one of these left implicit.
- Implement per-key state as a sorted deque of event times plus a set of flagged window ids, both retired at
watermark - 660 s. - Fixture 1, in order: identical amounts at t, t+1 min and t+9 min produce one flag. A fourth at t+11 min evicts t+1 exactly under the half-open rule
pop while front <= new - 10 min, leaving two events and no second flag; change that comparison to strict<and the same input flags twice. Pick one and write it in the spec. - Fixture 2, out of order: deliver the same three events as t+9, t, t+1 and assert the flag fires on the third arrival with the same window id as fixture 1.
- Fixture 3, too late: the t event arrives 90 seconds after the watermark passed it, so no flag fires and
late_droppedincrements by one. - Replay all three fixtures under twenty random arrival orders and assert the flag set is identical whenever every event is inside the lateness bound.
Follow-up
- Make the threshold and window configurable without rebuilding all in-flight state on every change. What does that constrain in the data structure?
- Two stream partitions hold events for the same token. What does that force the partitioning key to be?
- An event arrives three hours late. Does any answer change, and who is told?
Add and backfill business_date on a live ledger table
ledger_entry holds 4 billion rows, is append-only, takes 10,000 inserts per second, and every reporting query currently derives the business date as posted_at::date. You must add business_date date NOT NULL, populated from the cutoff rule (17:00 in the account's own timezone), backfilled across all history, indexed, and cut over, with no write downtime and no long-held lock. Give the ordered migration steps with the lock each one takes, how you make the backfill restartable and throttled, and how you retire the old expression safely.
Approach
- Add the column nullable and with no default. ALTER TABLE ... ADD COLUMN takes ACCESS EXCLUSIVE but is a catalogue-only change held for microseconds. The hazard is the lock queue, not the statement: a blocked ALTER waits behind one long reader holding ACCESS SHARE, and every query arriving afterwards queues behind the ALTER's pending ACCESS EXCLUSIVE, so set lock_timeout to a couple of seconds and retry rather than letting a metadata change take the table down.
- Deploy the write path before the backfill, so new inserts populate business_date from the cutoff rule while reads stay on the old expression. The backfill then chases a closed set with a fixed upper bound instead of a moving target.
- Backfill in bounded batches keyed by entry_id range, on the order of 50,000 rows per statement, committing between batches and recording the high-water mark in its own table so a killed run resumes instead of restarting. WHERE business_date IS NULL makes each batch idempotent, and the pacing is set by replica lag and dead-tuple growth rather than CPU, since each UPDATE writes a new row version and the WAL volume is proportional to the rows touched.
- Install the constraint without a blocking scan: ALTER TABLE ... ADD CONSTRAINT ck_business_date CHECK (business_date IS NOT NULL) NOT VALID takes a brief ACCESS EXCLUSIVE and scans nothing, then VALIDATE CONSTRAINT takes SHARE UPDATE EXCLUSIVE and runs alongside reads and writes. On PostgreSQL 12 and later, SET NOT NULL can then use the validated CHECK and skip its own full scan; on 11 and earlier it always scans, so the CHECK is the migration on those versions.
- Build the index with CREATE INDEX CONCURRENTLY, which avoids ACCESS EXCLUSIVE at the cost of two table passes, cannot run inside a transaction block, and on failure leaves an INVALID index that must be dropped and rebuilt rather than reused.
- Cut over behind a flag: run the new and old expressions side by side for one reporting cycle and compare totals per day, since the cutoff rule will legitimately move entries near 17:00 across the boundary. Only once they reconcile do you retire the posted_at::date expression index, and you keep posted_at as the ordering key rather than repurposing it.
Follow-up
- Reporting now wants ledger_entry partitioned by business_date. Why can this not be another ALTER, and what is the migration instead?
- Nightly totals move for the days around the cutoff change. How do you tell a correct restatement from a backfill bug?
- The backfill is halfway done when a replica falls 20 minutes behind. What do you throttle, and what do you refuse to throttle?
Rebuild a statement with a running balance from entries alone
From ledger_entry(entry_id bigint and monotonic, account_id, direction, amount_minor, currency, business_date, posted_at) produce one month's statement for a single account: every entry in order, its signed amount, and the running balance after it, starting from a supplied opening balance. The account is a customer deposit, so a credit increases it. Also return the first business_date in the month on which the running balance went negative, or null if it never did. Write the query using window functions, state which frame you depend on, and say what makes the ordering deterministic.
Approach
- Sign the amount first: CASE WHEN direction = 'credit' THEN amount_minor ELSE -amount_minor END, because the sign lives in direction and never in the column. State the convention out loud, since a customer deposit is a liability of the institution and a credit increases it, while for an asset account the same expression inverts.
- Compute the running balance as SUM(signed) OVER (PARTITION BY account_id ORDER BY business_date, entry_id ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), then add the opening balance as a scalar. The opening figure is a constant for the statement, not a second window.
- Be explicit about the frame, because it is the whole exercise: with an ORDER BY and no frame clause the default is RANGE UNBOUNDED PRECEDING AND CURRENT ROW, which includes every peer row tied on the ordering key. Ordering on business_date alone therefore reports the same end-of-day figure on every line of that day, and the statement still looks plausible.
- Make the order deterministic with a column that has no ties: business_date has ties by construction, entry_id is monotonic and unique, and posted_at is neither guaranteed unique nor correct as an ordering key when a backdated entry posts late.
- Get the first breach from the same computation rather than a second pass: wrap the running balance in a subquery and take MIN(business_date) FILTER (WHERE running_balance_minor < 0). LAG is the wrong tool here, because the question is about a level rather than a change.
- Support it with an index on (account_id, business_date, entry_id) so the partition and the order both come from the index; then confirm in EXPLAIN that there is no Sort node above the index scan.
Worked solution 25 min
- Seed one account with 40 entries across a month, including three on the same business_date with mixed directions and one backdated entry posted late.
- Write the signed-amount expression and the SUM window with an explicit ROWS frame ordered by (business_date, entry_id).
- Wrap it and add MIN(business_date) FILTER (WHERE running_balance_minor < 0) as first_negative_date.
- Re-run with the frame clause removed and with entry_id dropped from the ORDER BY, and record exactly which rows change.
Follow-up
- An entry for 3 March posts on 7 March, after the statement for that week was sent. Where does it appear, and what does the running balance do?
- The same statement has to be reproducible a year from now. What stops it changing, and what would silently change it?
- At what account size does deriving this per request stop being viable, and what would you materialise first, a daily closing balance or a monthly one?
Implement input validation and error handling for a multi-step user re…
Implement input validation and error handling for a multi-step user registration form that connects to a backend service.
Approach
- Say what you would check first and why it is the highest-information step.
- Work from the requirement backwards to the design.
- Clarify what is being asked and what a complete answer contains.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Design a scalable notifications service that handles millions of SMS a…
Design a scalable notifications service that handles millions of SMS and email alerts daily, ensuring at-least-once delivery.
Approach
- State your assumptions explicitly before working the problem.
- Say what you would check first and why it is the highest-information step.
- Work from the requirement backwards to the design.
Follow-up
- How would you know your answer was wrong?
- What assumption would you test first?
Capture endpoint that survives concurrent duplicate retries
POST /payments/{intent_id}/capture carries an Idempotency-Key header and an amount. Callers retry on timeout, and two retries can land concurrently on different instances. You have idempotency_key(id, scope, key, UNIQUE(scope,key), request_fingerprint bytea, status in_progress|completed|failed, response_status, response_body jsonb, locked_at, completed_at, expires_at). The processor capture takes 200 to 2,000 ms. Design the path so exactly one capture reaches the processor, every duplicate receives the identical response, and a crash between the processor call and your commit converges. Name the single statement that is the concurrency control.
Approach
- The concurrency control is INSERT INTO idempotency_key (...) VALUES (...) ON CONFLICT (scope, key) DO NOTHING RETURNING id, and it must commit before the processor call. A returned row means you own the effect; zero rows means you lost and must read the winner's result. A SELECT-then-INSERT check cannot substitute: two requests both read 'absent' and both proceed, and the window is exactly the concurrency you are defending against.
- Commit the in_progress row in its own short transaction. A concurrent duplicate insert blocks on an in-flight conflicting insert until that transaction ends, so wrapping the 2 s processor call in the same transaction turns every duplicate into a 2 s lock wait and a retry storm into pool exhaustion.
- Define loser behaviour per status rather than uniformly: completed replays response_status and response_body unchanged; in_progress returns 409 with Retry-After and performs nothing; failed splits by cause, since a terminal processor decline should replay but a transport failure should let the key be retried. Getting this wrong in the safe direction (replay a decline) is better than returning an error for a capture that succeeded.
- Fingerprint the canonicalised body with SHA-256 and compare on every hit. Same key with a different amount is a client bug and must return 409 or 422, never the cached response, because returning the cached body silently captures the old amount and looks successful.
- Pass the same key to the processor so deduplication holds end to end, and generate it once at the originating caller. A key regenerated per attempt leaves every line of idempotency code in place while disabling the mechanism entirely.
- Converge after a crash by querying the authoritative side rather than guessing: a reaper picks up rows in_progress past locked_at plus a bound, asks the processor for that key or the intent's processor_reference, and completes the row from the answer. Set expires_at longer than the caller's full retry schedule and document that a replay after expiry is a new request.
Worked solution 30 min
- Implement the endpoint with the ON CONFLICT DO NOTHING insert committed before the processor call, and a processor stub that counts calls and sleeps 1,500 ms.
- Drive 50 concurrent identical requests through two application instances.
- Repeat with the same key and the amount changed by one minor unit.
- Kill the instance between the stub's response and the local commit, restart, and run the reaper.
Follow-up
- The processor does not honour idempotency keys. What is the end-to-end design now, and what can you no longer promise?
- Two merchants send the same key value. What makes that safe?
- You keep keys for 24 hours at 3,000 requests/s. Size the table and the index, and say what expires them.
Settlement postings plateau at 310 per second and deadlock
Ledger postings against one pooled merchant settlement account plateau at about 310 committed transactions per second. Adding workers beyond 24 raises latency linearly and leaves throughput flat. Separately, about 0.4% of two-account transfers abort with SQLSTATE 40P01. Each posting takes SELECT ... FOR UPDATE on the materialised balance row, validates a floor, inserts the entries, then updates the balance. Explain both numbers, give the fix for each, and state precisely what sharding the hot balance would cost the floor check.
Approach
- Compute the ceiling instead of guessing. A row-level exclusive lock serialises every transaction touching that row, so the maximum committed writes per second is 1 divided by the lock hold time, where hold runs from FOR UPDATE to COMMIT and includes the entry inserts, the WAL flush and anything else inside the transaction. 310 per second implies about 3.2 ms held. Measure it via pg_locks joined to pg_stat_activity rather than inferring it.
- Recognise what the flat-throughput, rising-latency curve proves. Past the ceiling, extra workers only lengthen the wait queue; that is serialisation, not saturation, and no amount of CPU, replicas or pool size changes it. Establishing this rules out the three most common wrong fixes before proposing anything.
- Shorten the critical section before sharding anything. Take the lock last, never hold it across an application round trip or a processor call, and replace SELECT-then-UPDATE with one conditional statement: UPDATE balance SET amount_minor = amount_minor - $1 WHERE account_id = $2 AND amount_minor - $1 >= floor_minor. It needs no prior read and holds the row only for that statement, so halving hold time doubles the ceiling for free.
- Treat the 40P01 as a separate defect with a separate fix. Two transfers moving money in opposite directions between accounts A and B acquire the two row locks in opposite orders and wait on each other until the detector aborts one. Acquiring locks in a deterministic order, such as ascending account_id, makes the cycle impossible rather than merely rarer; a bounded retry on 40P01 remains prudent but is no longer the mechanism.
- Only then shard, and price it honestly. N sub-rows multiply the ceiling by roughly N, but the floor becomes a predicate over N rows that a single-row conditional UPDATE cannot express. Either each sub-row carries its own floor, which over-restricts by refusing a payment while funds sit on another shard, or you move to SERIALIZABLE with a bounded retry on 40001 across the sub-rows. Establish first whether this pooled clearing account has a floor at all, because if it does not, sharding is nearly free and the whole trade-off disappears.
Follow-up
- At what N does rebalancing funds between sub-rows cost more than the throughput it buys?
- How would you measure lock hold time in production without attaching a profiler?
- Does moving to SERIALIZABLE eliminate the 40P01 aborts?
Four days sample coding, design, fundamentals and the practical rounds at deliberately shallow depth, which is enough to surface the topics you did not know were in scope. That map, rather than a guess made on day one, decides where the last three days go.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Assessment-style coding: strings and arrays
- Solve Filter Odds and Reverse Evens, String Replace and Grouping, Remove Duplicates While Preserving First-Appearance Order and Count Numbers Whose Successor Exists, each with a per-question timer you do not extend
- Write down the edge cases the prompt examples leave out (empty input, a single element, all duplicates, trailing punctuation) and test every solution against them
- Solve Bounding Box From Coordinates in one pass and state its complexity out loud
Deliverable: Five timed solutions, each marked finished or late, with an edge-case list attached.
Practice prompt ↗Practice prompt ↗Worked solution ↗02Data-structure coding for the live-coding interviews
- Implement the reported custom stack with push, pop and a constant-time min (then sum) by storing the aggregate-so-far with each element, and explain why this works for aggregates you can update from the previous value (min, sum, or mode with a count map) but not for median, which needs order statistics such as two heaps
- Write rolling statistics over a transaction stream using a map keyed by account, then extend it to a sliding window
- Solve the reported unique-combinations problem with backtracking and duplicate skipping, and the character-code differences between two long strings
- Optional depth: work through the existing out-of-order stream exercise (drill-coding-3) to practice windows and watermarks
Deliverable: Four solutions narrated aloud with brute force, improvement and complexity stated for each.
Practice prompt ↗Practice prompt ↗03Project round: environment and a working API
- Set up a boilerplate app in the stack you will use (for example Rails, Sinatra, Spring Boot or a React front end with an API), connected to a local database
- Build a task manager like the reported one against your own practice spec: create, list, update and delete tasks, persisted to the database, plus one migration that adds a column
- Restart from a cold start and confirm the app boots, migrates and serves a request without fixes
Deliverable: A tested local project that runs from a cold start, plus a written checklist of setup steps.
Practice prompt ↗Practice prompt ↗04Project round: validation, refactoring and debugging
- Add input validation and error handling for a multi-step registration form that posts to your back end, returning clear field-level errors
- Refactor a React component to reduce unnecessary re-renders and simplify its state, and note what changed and why
- Deliberately break a migration or a namespaced model relationship, then fix it while narrating what you check first
Deliverable: Validation and error paths working in your project app, plus a short log of the break-and-fix debugging session.
Practice prompt ↗Practice prompt ↗Worked solution ↗05System design: ledger and partner APIs
- Design the schema and consistency model for a high-volume ledger, and state which operations need strong consistency and which reads can lag
- Design the API for asynchronous loan decisions from external bank partners: request, callback or polling, idempotency and the pending state
- Work through the existing idempotent capture exercise (drill-design-4) and the running-balance SQL exercise (drill-sql-2) to check your schema reasoning
Deliverable: Two design sketches, each with a schema, API contract and a stated consistency choice.
Practice prompt ↗Practice prompt ↗06System design: throughput and real-time systems
- Design a notifications service for SMS and email with at-least-once delivery: queueing, retries, deduplication on the consumer and delivery status
- Design rate limiting for distribution APIs: choose an algorithm, where the counter lives and what a rejected caller receives
- Design a multiplayer online chess game covering the database schema, API endpoints, move validation and state synchronization
Deliverable: Three designs, each opening with the clarifying questions you would ask about requirements, volume and consistency.
Practice prompt ↗Practice prompt ↗07Behavioral, the project deep-dive and a mock onsite
- Prepare STAR answers for the reported prompts: most complex project and its trade-offs, a tight deadline, a disagreement with product over technical debt, a production mistake and a disorganized codebase
- Rehearse your technical-screen project walkthrough, including rejected alternatives
- Run a back-to-back mock of one coding problem, one design prompt and one behavioral answer, and note where your structure slipped between them
Deliverable: Five STAR stories on cards, one rehearsed project walkthrough and notes from the mock loop.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
The reported behavioral prompts cover project ownership, working under deadline pressure, disagreeing with product managers, production mistakes and bringing order to a messy codebase. Prepare specific STAR stories. For each one, name the decision you made, the alternatives you considered and the measurable result, and include what you would do differently.
How do you handle disagreements with product managers regarding techni…
How do you handle disagreements with product managers regarding technical debt versus feature delivery?
Approach
- Name the disagreement and how you resolved it with evidence.
- State the situation in two sentences and spend the rest on the reasoning.
- Give the blast radius: what could have broken, and what you measured.
Follow-up
- How did you know your change caused the improvement?
- What did you decide not to do, and why?
Describe a time when you had to meet a tight deadline under resource c…
Describe a time when you had to meet a tight deadline under resource constraints. How did you prioritize tasks?
Approach
- Close with what you would do differently, concretely.
- Pick a story where you made the decision, not one where you watched it.
- State the situation in two sentences and spend the rest on the reasoning.
Follow-up
- What did you decide not to do, and why?
- How did you know your change caused the improvement?
Estimate a reconciliation rebuild you have never attempted
You are asked how long it takes to replace a reconciliation service matching 30 million settlement lines a day against the ledger, including a bounded fuzzy fallback for netted fees and an ageing model for breaks. You have never built one. Produce an estimate, the range around it, and the two or three unknowns that dominate that range. Then describe a time you estimated unfamiliar work: what you did in the first day to shrink the range, what you committed to publicly, how far off you were, and what you would tell the requester differently now.
Approach
- The probe is whether you can be useful under uncertainty without either refusing to estimate or inventing false precision. Give a number with an explicit range and the basis for both, then immediately name what would move it, rather than asking for two weeks of discovery first.
- Decompose into parts with different uncertainty profiles. The hash join on (external_reference, amount_minor, currency, business_date) over 30 million lines is well understood engineering and estimates tightly; the fuzzy fallback for netted and fee-adjusted lines does not, because its scope is defined by whatever the files actually contain; the ageing and break workflow is mostly operations-facing surface area, which estimates by counting screens and states.
- Name the dominating unknowns concretely: how many distinct file formats and cutoff conventions the sources use, what fraction of lines are netted rather than itemised, and whether business_date is derivable from any field in the file or must be reconstructed from the cutoff rule. Each is a factor on the fuzzy path, not a percentage on the whole.
- Describe the first-day range-shrinking work, which is the part that separates strong from generic: take one real file, count distinct formats, measure the netted fraction, and attempt the exact join on a single day of postings to see what the residual actually is. One day of that typically converts a 3x range into something near 1.5x.
- Commit in a form that survives being wrong: a range plus a checkpoint date at which you will replace it with a narrower one, and an explicit statement of what you will cut first if the range turns out to be optimistic.
- In the retrospective half, give the real numbers: the estimate, the actual, and the specific thing that consumed the difference. Answers that were within 10 percent are less informative than answers that were 2x off for a nameable reason.
Follow-up
- The requester wants one number, not a range, for a board deadline. What do you give them?
- Your one-day probe finds 40 percent netted lines instead of the 5 percent you assumed. What changes in the plan, not just the estimate?
- What do you cut first if you are at the deadline and the fuzzy fallback is not done?
- 01
Tell me about the most technically complex project you have driven from start to finish. What were the trade-offs?
- 02
Describe a time when you had to meet a tight deadline under resource constraints. How did you prioritize tasks?
- 03
How do you handle disagreements with product managers regarding technical debt versus feature delivery?
- 04
Tell me about a time you made a technical mistake that impacted production. How did you resolve it and what did you learn?
- 05
Describe an experience where you had to work with a highly disorganized codebase or team. How did you establish best practices?
- 06
Explain a technical system you built to a nontechnical audience.
Is this an official Upstart interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Upstart. Rounds and questions reflect what candidates have reported, not a process Upstart has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How difficult is the Upstart Software Engineer interview?
Candidates describe most individual coding questions as easy to medium. The difficulty comes from the strict per-question time limits on the online assessment and from building a working feature live in the Project round. Prepare for speed and finishing, not only for hard algorithm topics.
PracHub interview research ↗What is the Project round, and how should I prepare for it?
Candidates describe building or extending a working application, such as a simple web app or API, live in their own local environment while sharing their screen. Before the interview, set up a boilerplate app in your preferred language and framework (for example React, Rails or Spring Boot), connect it to a local database, and test a migration and a model relationship from a cold start.
PracHub interview research ↗How is my level (L4, L5/Senior, Principal) decided?
Candidates report hiring at L4, L5/Senior and Principal. Reports say the level comes from performance across the onsite, with system design and the behavioral/values interview weighing most. If you are targeting senior or principal, prepare design answers with explicit trade-offs and stories where you led technical decisions. Ask your recruiter which level the loop is set to.
PracHub interview research ↗What kinds of coding problems should I practice?
The bank for this role is mostly practical: string rewriting and grouping, array filtering and reordering, de-duplication that preserves order, bounding boxes, and billing or revenue simulations. Reported coding questions also include a custom stack with a calculation over its elements, rolling statistics with a map, and combination search. Practice picking between hash maps, sets and stacks, and stating complexity.
PracHub Software Engineer practice ↗Which system design topics come up?
Reported design questions include a multiplayer online chess game, an API for asynchronous loan decisions from bank partners, rate limiting for distribution APIs, a high-volume ledger schema and consistency model, and a notifications service with at-least-once delivery. For each one, cover the schema, the API contract, and where you need strong versus eventual consistency.
PracHub Software Engineer practice ↗Sources & methodology 3 sources ↗
Official role evidence, timestamped platform data and clearly labeled preparation advice.
- 01PracHub interview research ↗
PracHub editorial research into this company and role, maintained with this guide. Candidate-reported, not an employer publication.
platform · Accessed 2026-09-24 - 02PracHub Software Engineer practice ↗
Cross-company practice questions for this role.
platform · Accessed 2026-09-24 - 03PracHub interview preparation framework ↗
The framework the preparation plan follows.
platform · Accessed 2026-09-24