The source notes describe Ramp as combining corporate cards, expense management, accounts payable automation and procurement in one platform. Software engineers are described as working on financial ledgers, real-time transaction authorization, fraud detection and the interfaces customers use. Money is involved throughout, so correctness around balances, duplicates and failures carries real weight, and it shows up directly in the reported interview questions.
The notes describe engineers owning features end to end, from specification through deployment and monitoring. The work spans backend services that handle asynchronous payment processing, frontend applications, and AI-assisted automation. The languages and tools the notes list include Python, TypeScript/JavaScript, Go or Java, React and PostgreSQL. The must-have skills they name are data structures, algorithms, object-oriented design, building and consuming REST APIs, and relational query design. Fintech background, React depth (for frontend and fullstack roles), and experience with message queues or AI development tools are listed as nice-to-haves.
For the interview, this means practical problems rather than puzzles. The reported questions include querying flight records by timestamp, following a chain of HTTP endpoints while handling 4xx and 5xx responses, and building ledgers, file systems and task managers in levels that each extend the last. They also include React builds such as a spreadsheet or calendar, and design questions such as a card transaction pipeline. The notes add that some technical rounds allow or expect an AI assistant, and that interviewers there check whether you understand the generated code. Prepare to write complete, tested code and to explain every line of it.
Online Assessment
reportedThe source notes describe this stage as an asynchronous assessment or puzzle challenge built from practical coding tasks, and name CodeSignal as one format. Some candidates report starting with a recruiter screen instead, so ask which stage opens your process. Treat it as a test of execution. The questions reported for this role are practical: flight records, transaction totals by minute, string conversion, in-memory stores with TTL, and class builds that grow in levels. What pays off is writing correct, complete code against stated requirements and checking edge cases before you move on. Memorising puzzle tricks pays off less. When a task comes in parts that build on each other, finish and verify each part before you read the next. A bug left in an early part tends to break every later one.
What to demonstrate
- Practical execution: turning written requirements into working, well-structured code within the time allowed
- Edge-case handling and data modelling in state-heavy tasks such as ledgers, key-value stores and record lookups
- Whether code written for an early part can take on later requirements without a rewrite
How to prepare
- Work multi-level problems from the bank under a timer, such as Banking Tasks Class, the multi-level task manager and the in-memory cloud storage system. Finish and test each level before you read the next one
- Before you submit any part, run it on an empty input, a single element, duplicate timestamps and an operation on a missing key
- Rehearse the standard-library calls you lean on (sorting with a key, dictionaries of lists, binary search on a sorted list) so you do not spend assessment time looking them up
Recruiter Screen
reportedThe source notes describe a screening call about your background and your fit for the role. Use it to collect the information that shapes the rest of your preparation. Ask which track and level the loop is for (backend, frontend or fullstack), whether a system design round is included, whether any round uses an AI assistant, and whether live coding happens in your own editor. The reported question set spans backend coding, React application builds and system design. Knowing your track tells you where to spend the remaining days.
What to demonstrate
- How clearly you summarise your background: what you built, what you personally owned and what changed because of it
- How well your experience fits the track and level of the role
- Your reasons for the role, and how you describe the work you want to do next
How to prepare
- Prepare a short account of one or two projects covering what you built, what you owned and the outcome. The behavioral round's 'project you are most proud of' prompt draws on the same material
- Ask which track and level the loop is calibrated to and which rounds follow, then plan your week from the answer rather than from the job posting
- Ask about round formats: your own IDE or a shared editor, whether an AI assistant is allowed and with what limits, and which languages you can use
Technical Phone Screen
reportedThe source notes describe a live technical interview built around pair programming. They also say that several phone-screen problems involve querying timestamped records or nested API paths efficiently. Reported questions of that shape include locating a user from flight records at a given time, and following a chain of HTTP endpoints to a maze exit while handling 4xx and 5xx responses. Because this is pair programming, state your assumptions before coding. For example: what does a query at exactly a departure timestamp return, and should a 5xx be retried? Keep the code runnable at every step, and extend it cleanly when follow-ups arrive rather than starting over.
What to demonstrate
- Practical execution: a working, tested solution rather than a sketch
- The choice of structure for timestamped lookups, such as per-user records sorted by time with binary search instead of repeated linear scans
- Resilient HTTP handling: telling permanent client errors apart from retryable responses (5xx, timeouts, 429 and 408), bounding retries and never revisiting a URL
- How clearly you explain decisions while pairing
How to prepare
- Solve User Location Query on Flight Data and Flight Records and User Location. Sort each user's flights by time, binary-search for the last event at or before the query time, and say explicitly what a query during a flight returns
- Solve URL Maze with Error Handling and Clue-Driven HTTP Sequencing with a requests-style client. Use a visited set, bounded retries with backoff for 5xx, timeouts, 429 Too Many Requests and 408 Request Timeout (honouring Retry-After when it is sent), no retry on other 4xx, and an explicit exit condition
- Practise in your own editor with the language docs open. The source notes report that live coding is often open-book, but confirm this for your loop
Virtual Onsite Loop
reportedThe source notes describe several technical rounds, including coding and system design, plus a behavioral interview with a hiring manager. The source does not map individual questions to onsite rounds. The reported questions for the role fall into these categories: multi-level class design (a banking ledger, a file system with lock/key security, a task manager); application engineering in React (a calendar day view, a spreadsheet with formula dependencies, an email client, Wordle or tic-tac-toe); and architecture (a corporate card transaction pipeline, a sliding-window rate limiter). The notes also say some technical rounds allow or expect an AI assistant with a prompt limit. If yours does, be ready to explain the generated code line by line. Weight your preparation by the track and level the recruiter gave you.
What to demonstrate
- Pragmatic system design: simple, workable designs that address concurrency, failure modes and data consistency without over-engineering
- Clean, modular class design that absorbs each new level of requirements
- Where an AI assistant is allowed: directing it well, catching its bugs and explaining how the generated code works
- Product thinking in the hiring-manager conversation: connecting technical choices to user and business outcomes
How to prepare
- Design the corporate card transaction pipeline end to end: authorization, settlement events, fraud signals and notifications. Add idempotency keys and a plan for duplicate or out-of-order events, then work this guide's ledger and settlement exercises
- On a frontend or fullstack track, build the spreadsheet in React (dependency graph, recompute order, cycle detection) and the calendar day view (grouping overlapping events into columns)
- Rehearse the reported behavioral prompts, including how you use AI in daily work and how you check its output
- Keep one fixed set of facts per project (scale, team, what you owned) so the design and behavioral rounds hear the same account
9 candidate reports. Individual accounts describe a particular role and hiring cycle.
Ramp Account Executive interview experience: 45-minute presentation
The process was long. The recruiter kept me updated, but the timeline still stretched out to roughly six interviews. The biggest demand was a 45-minute presentation that took about 20 hours to prepare. I received positive feedback during the stages I completed, so I expected a clearer ending. Instead, I got a rejection email with almost no explanation. After putting in that much time, I wished th…
Read full experienceRamp Software Engineer interview: AI-assisted development screen
After a recruiter reached out, I had a short screen that was mostly about how I use AI day to day. We discussed what I had built or worked on with coding assistants and answered questions directly about AI-assisted development. The recruiter did not go deeply into much else, so the AI emphasis was clear. The next step was another technical conversation with a practical coding feel. It had two par…
Read full experienceRamp Applied AI Engineer Interview Experience — Rejected Before the 25-Minute OA Even Closed
View report detailsRamp Software Engineer Interview Experience — A Binary Search Flight-Tracking Question and No Feedback
View report detailsRamp Software Engineer Interview Experience — Four-Round Onsite With an AI Coding Round, Rejected
View report detailsPracHub editorial advice for the preparation topics above.
Hard-coding level 1 of a multi-level class problem so that the next level forces a rewrite
Reported problems such as the banking ledger, file system and task manager add requirements in levels: transfers, scheduled payments and top accounts; copies and locks; expiring tasks. Model the entities first, for example accounts or files as objects in a dictionary keyed by id, with an operation log if history might matter later. Keep each operation a small method that validates its input and returns an explicit result for failures such as a missing account or insufficient funds. Do not bake assumptions like 'a balance only changes on deposit' into shared code. Rerun the earlier levels' tests before starting a new one.
Following the HTTP maze on the happy path only
The maze and clue-driven request questions add follow-ups about 4xx and 5xx responses, so decide the policy before you write the loop. Most 4xx codes (400, 401, 403, 404) mean the request itself is wrong: record it and stop, or skip that branch, rather than retrying. Two 4xx codes are the exception: 429 Too Many Requests and 408 Request Timeout are retryable, so back off and retry them, waiting at least as long as a Retry-After header asks. The source notes list rate-limit backoff logic among the API-traversal topics. A 5xx or a timeout is often transient: retry a bounded number of times with backoff. Keep visited URLs in a set so a cycle cannot loop forever, parse every response defensively, and write the exit condition as an explicit check.
Submitting AI-generated code you cannot explain line by line
The source notes say that where an AI assistant is allowed, interviewers test your understanding of the code, not just its output, and that prompts may be capped. Write one focused prompt per piece of work. Read what comes back before you run it, and test it on edge cases you chose yourself. Be ready to say why it used a heap, a dictionary or a particular loop bound, and fix off-by-one errors and missing cases yourself instead of re-prompting.
Leaving a coding task partly working while polishing one part of it
The source notes describe completeness as critical: fully passing solutions are expected in coding stages. Get a correct, simple version of every required part running first, then optimise. For the minute-bucket aggregation, for example, floor each timestamp to its minute and sum into a dictionary before you think about output ordering or streaming. Pace yourself across the parts of a multi-part task instead of spending most of your time on the first.
Designing the card transaction pipeline or ledger without guarding against money being moved twice
In design questions like the card pipeline, the ledger or the rate limiter, point out where a retried request, a duplicated settlement event or two concurrent writes could apply the same effect twice, and close each gap. Use idempotency keys enforced by a unique constraint, store amounts as integer minor units, derive balances from ledger entries, and use row locks or conditional updates on hot rows. Keep the rest as simple as the requirements allow. The source notes say interviewers weigh practical simplicity over over-engineering.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Write a function that accepts a list of transaction records (timestamp…
Write a function that accepts a list of transaction records (timestamps and amounts) and returns aggregate transaction totals broken down by minute buckets.
Approach
- Walk one small example through your approach before writing the whole thing.
- Name the brute-force solution and its complexity before improving on it.
- State the target complexity and say which constraint rules the naive version out.
Follow-up
- Which test case would catch an off-by-one here?
- How does this change if the input no longer fits in memory?
Given a starting URL, make chained HTTP requests where each response c…
Given a starting URL, make chained HTTP requests where each response contains clues for the next endpoint to follow a "maze exit" puzzle, with progressive follow-ups handling 4xx and 5xx error codes.
Approach
- Walk one small example through your approach before writing the whole thing.
- Choose the data structure from the access pattern, not from familiarity.
- State the target complexity and say which constraint rules the naive version out.
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?
Convert every `snake_case` string token into `camelCase` across a sent…
Convert every snake_case string token into camelCase across a sentence while preserving non-target formatting and punctuation.
Approach
- Choose the data structure from the access pattern, not from familiarity.
- Walk one small example through your approach before writing the whole thing.
- Name the brute-force solution and its complexity before improving on 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?
Implement a function `get_user_location(time)` and `get_user_with_most…
Implement a function get_user_location(time) and get_user_with_most_flights given a dataset of flight records containing departure/arrival airports, user IDs, and timestamps.
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Name the brute-force solution and its complexity before improving on it.
- Choose the data structure from the access pattern, not from familiarity.
Follow-up
- Which test case would catch an off-by-one here?
- How does this change if the input no longer fits in memory?
Derive per-account balances and catch unbalanced transactions
You are given ledger_entry rows streamed in entry_id order: transaction_id, account_id, direction (debit or credit), amount_minor (a positive int64), currency, business_date. Up to 500 million rows, at most 20 million distinct (account_id, currency) pairs, and the entries of one transaction are contiguous in the stream. In a single pass with no re-reads, return the closing balance per (account_id, currency) and the transaction_id of every transaction whose entries do not sum to zero within each currency. State your time and space bounds.
Approach
- Normalise the sign at read time from
direction, not from the amount:signed = +amount_minorfor debit,-amount_minorfor credit (state which convention you picked). The schema constrainsamount_minor > 0precisely so the sign lives in exactly one place. - Hold one hash map keyed
(account_id, currency)to an int64 running total. Twenty million keys at 16 bytes of payload plus map overhead is order 1 GB in most runtimes — quote the number, and offer the fallback: partition the stream byhash(account_id) % Pand run P passes for 1/P of the memory. - Ride the zero-sum check on the same pass. Because a transaction's entries are contiguous, keep a tiny
currency -> int64map for the currenttransaction_idonly, test it against zero on the boundary and at EOF, then clear it. That is O(currencies in one transaction), typically one or two. - Bound the arithmetic explicitly. Int64 holds about 9.22e18, so overflowing one account across 500 million entries needs an average of 1.8e10 minor units per entry — safe here, but use a checked add so an adversarial file fails loudly rather than wrapping.
- Complexity: O(n) time, O(distinct account-currency pairs) space, one sequential pass, no sort. The zero-sum check adds no asymptotic cost, which is the argument for doing it here rather than in a second job.
Worked solution 20 min
- Write the sign rule down in one sentence before any code, naming which side debit is positive on, and apply it at read.
- Implement with two maps —
balances: (account_id, currency) -> int64andtxn: currency -> int64— plus the currenttransaction_id. - On a change of
transaction_id, assert every currency intxnsums to zero, record the id if not, then clear. - Feed a fixture: one 2-entry transaction that balances; one 4-entry transaction with USD and JPY legs that balances within each currency; one 3-entry transaction off by a single minor unit.
- Re-run with the entries shuffled inside each transaction to prove the result is order-independent within a transaction.
Follow-up
- Entries of a transaction are no longer contiguous. What does the zero-sum check cost now, and which is cheaper: buffering open transactions or an external sort on
transaction_id? - How would you produce the same balances as of an arbitrary
business_datewithout a second full scan? - The job is restarted after a crash halfway through the file. What makes the second run produce identical output?
Make a charge endpoint safe under concurrent duplicate retries
idempotency_key holds id, scope, key, request_fingerprint (SHA-256 over the canonicalised body), status (in_progress, completed, failed), response_status, response_body, locked_at, completed_at, expires_at, created_at. Fifty identical create-payment requests carrying the same scope and key reach four application instances inside the same 20 ms. Give the DDL constraint and the exact statements the handler runs so that exactly one payment_intent is created and all fifty callers receive the same response body. State what you return when that key arrives with a different fingerprint, and what an arrival after expires_at means.
Approach
- Put the concurrency control in the schema: UNIQUE (scope, key). A SELECT-then-INSERT cannot work because both transactions can read nothing before either commits, so the check passes twice and the constraint then surfaces as an error on a payment that succeeded.
- Claim the key with INSERT ... ON CONFLICT (scope, key) DO NOTHING RETURNING id. A conflict returns zero rows rather than the existing row, so branch on rowcount: the winner proceeds, the loser reads the stored row.
- Keep that path on READ COMMITTED deliberately. The loser's follow-up SELECT takes a fresh statement snapshot and therefore sees the winner's committed row; under REPEATABLE READ the transaction snapshot predates that commit, the row stays invisible and the loser concludes the key does not exist.
- Split the work across two transactions because the processor call cannot sit inside one: commit the in_progress row with locked_at first so losers can see a claim, perform the effect, then write payment_intent plus status=completed with response_status and response_body in a single second transaction.
- Handle the crash window explicitly: a row stuck in_progress past its lease is an unknown outcome, not a failure, so the reaper queries the processor for that key before deciding. A loser that sees in_progress returns 409 and retries rather than repeating the effect.
- Compare request_fingerprint before replaying anything. Same key with a different body is 409, never the cached response, because replaying confirms a payment the caller did not request; and set expires_at beyond the client's and the processor's maximum retry horizon, since a replay after it is a genuinely new request.
Follow-up
- The handler dies after the processor call and before the local commit. What does the next retry with that key observe, and how does the system converge on exactly one charge?
- Does the downstream processor honour an idempotency key of its own? Who mints it, and what breaks if a fresh one is generated per attempt?
- How do you purge rows past expires_at without the delete contending with the insert path?
Store multi-currency amounts and prove each transaction balances
ledger_entry holds entry_id, transaction_id, account_id, direction (debit or credit), amount_minor (bigint, CHECK > 0), currency char(3), source_type, source_id, business_date and posted_at. The service posts in JPY, USD and KWD. Specify the column types for money and the reference table that carries each currency's ISO 4217 minor-unit exponent, and say why that exponent must not be a constant in application code. Then write the query that returns every transaction_id whose entries fail to sum to zero within each currency, ordered by the largest absolute imbalance.
Approach
- State the representation: amount_minor is an integer count of minor units and the scale lives with the currency, not in the column. int4 tops out at 2,147,483,647 minor units, which is about 21.5 million units of a 2-exponent currency, so bigint, and the currency code travels on every row that carries an amount.
- Normalise the scale into currency(code char(3) primary key, exponent smallint, name) and join it only at display and parse boundaries. The exponent is 0 for JPY and KRW, 2 for USD and EUR, 3 for KWD, BHD, JOD, OMR and TND, so a hard-coded divide by 100 is wrong by 100x for JPY and by 10x for KWD, in opposite directions.
- Rule out binary floating point outright: IEEE 754 binary64 cannot represent 0.1, so repeated accrual drifts by a few minor units that later appear as reconciliation breaks. If a fixed-scale decimal is used instead, pin the scale per currency and name the single place rounding happens.
- Write the balance check as a grouped aggregate: sign the amount with a CASE on direction, GROUP BY transaction_id, currency, and HAVING the signed sum <> 0. The sign belongs in direction, and the CASE is the one place it becomes arithmetic.
- Then order in a second layer, because the ordering the question asks for cannot be written on the grouped query itself. PostgreSQL lets an output alias stand alone in ORDER BY but resolves anything inside an expression against the input columns, so ORDER BY abs(imbalance_minor) DESC raises SQLSTATE 42703, column "imbalance_minor" does not exist, while the bare ORDER BY imbalance_minor DESC is accepted and sorts signed rather than absolute. Wrap the grouped query and order by abs() outside it, or repeat the aggregate as ORDER BY abs(SUM(CASE ...)) DESC, which is legal because aggregates are allowed there.
- Group per (transaction_id, currency) rather than per transaction, because a cross-currency movement balances only within each currency, bridged by an explicit FX position account whose rate, source and timestamp are stored on the transaction.
- Note that no CHECK constraint can express this, since it spans rows: enforce it at write time with a DEFERRABLE INITIALLY DEFERRED constraint trigger that fires at commit, or by routing every posting through one function, and keep this query as the independent audit.
Worked solution 15 min
- Define currency(code, exponent, name) and seed JPY 0, USD 2, KWD 3; declare amount_minor bigint NOT NULL CHECK (amount_minor > 0) and currency char(3) REFERENCES currency(code).
- Write it in two layers so it runs: SELECT transaction_id, currency, imbalance_minor FROM (SELECT transaction_id, currency, SUM(CASE WHEN direction = 'credit' THEN amount_minor ELSE -amount_minor END) AS imbalance_minor FROM ledger_entry GROUP BY transaction_id, currency HAVING SUM(CASE WHEN direction = 'credit' THEN amount_minor ELSE -amount_minor END) <> 0) b ORDER BY abs(imbalance_minor) DESC.
- Post one clean capture, one deliberately unbalanced transaction, and one cross-currency transfer with an FX position account, then run the query.
- Convert 1000 JPY and 1000 KWD through the exponent table in both directions and confirm the round trip is exact.
Follow-up
- A transaction has a USD leg and a JPY leg. Which accounts appear, and where does the rounding residual land?
- How would you enforce the zero-sum rule at write time without serialising all postings behind one lock?
- Someone proposes storing a display amount alongside amount_minor. What goes wrong at the first rate change or rounding rule change?
Build a multi-tier banking ledger system across progressive levels (cr…
Build a multi-tier banking ledger system across progressive levels (creating accounts, deposit/withdraw/transfer, handling scheduled payments, and computing top accounts by activity).
Approach
- Name the failure you are designing for, then the recovery path.
- Fix the scope first: who calls this, how often, and what they do when it fails.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What breaks first when traffic grows ten times?
- What would you drop to keep the system up under load?
Design and implement a basic file system class supporting `FILE_UPLOAD…
Design and implement a basic file system class supporting FILE_UPLOAD, FILE_GET, FILE_COPY, and lock/key security mechanisms.
Approach
- Name the read and write paths separately; they rarely have the same bottleneck.
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- How does this behave when that dependency is down for an hour?
- What breaks first when traffic grows ten times?
Implement an in-memory JavaScript spreadsheet engine capable of adding…
Implement an in-memory JavaScript spreadsheet engine capable of adding, editing, and deleting columns, with dynamic formula dependency resolution across cells.
Approach
- Say what you would check first and why it is the highest-information step.
- State your assumptions explicitly before working the problem.
- Clarify what is being asked and what a complete answer contains.
Follow-up
- What assumption would you test first?
- How would you know your answer was wrong?
Ingest daily settlement files idempotently and restartably
A processor delivers one settlement file per business date containing 10 to 50 million lines, each with an external reference, a signed amount in minor units, a currency, a fee and the processor's settlement date. Files arrive late, are sometimes re-sent byte-identical, and are sometimes re-sent corrected under the same filename. Design ingestion: how a line becomes a settlement_line row, how a re-send avoids duplicating 50 million rows, how a correction supersedes the earlier version without deleting it, and how a run that dies at line 30 million resumes. State your throughput target.
Approach
- Treat the file as a versioned object rather than a stream of events. Key a file record on (processor_id, business_date, content_sha256): an identical re-send matches the digest and becomes a no-op in O(1), while a corrected re-send has a different digest and becomes file_version 2, which supersedes version 1 by stamping superseded_at on its lines rather than deleting them. Deleting them destroys the evidence for any break already raised against version 1.
- Give lines two levels of identity. UNIQUE (file_version_id, line_no) makes a resumed chunk unable to double-insert. Deduplication on business content must not collapse (external_reference, amount_minor, currency) into one row, because two identical genuine charges in one day are ordinary; if you need a business-level key, it has to include the line ordinal.
- Make restart cheap by committing in chunks of about 10,000 lines and recording a high-water line_no per file_version, so a crash costs at most one chunk. Smaller chunks mean more commit and WAL overhead; larger chunks mean more re-work after a failure. Pick from measured commit cost, not from a round number.
- Set the throughput target from the loading mechanism: a bulk COPY of narrow rows runs at order 10^5 rows/s per connection where row-by-row INSERT runs at order 10^3 to 10^4, so 50 million lines is minutes rather than hours. Parallelise by splitting the file into byte ranges aligned to line boundaries, one worker and one checkpoint per range.
- Partition settlement_line by business_date. A full re-ingest then rebuilds one partition instead of issuing a 50-million-row DELETE, and retention becomes a partition DETACH rather than a long-running vacuum problem.
- Validate before publishing the version: compare the file trailer's control totals against SUM(amount_minor) over the loaded rows, and fail the run on mismatch. A truncated file that loads cleanly otherwise looks exactly like a day when the processor sent less money.
Worked solution 30 min
- Generate a 10,000,000 line file, compute its SHA-256, and load it with COPY into a staging table partitioned by business_date, committing every 10,000 lines and recording the high-water line number.
- Ingest the identical file again and assert zero new rows, with no work done beyond the digest comparison.
- Alter 100 lines, re-ingest under the same filename, and assert a new file_version supersedes the first while version 1 rows remain fully readable.
- Kill the worker at line 4,000,000, restart it, and count the final rows.
Follow-up
- The same file starts ingesting twice concurrently from two workers. What stops the second one?
- The corrected file has fewer lines than the original. Which lines disappeared, and how does a break already raised against one of them get resolved?
- How do you know the file is complete rather than still being written by the transfer?
Duplicate captures appear only in production, roughly weekly
About once a week one payment is captured twice. The idempotency path is: SELECT id, response_body FROM idempotency_key WHERE scope = $1 AND key = $2; if no row, call the processor; then INSERT. The table has UNIQUE (scope, key). Logs for each duplicate show one successful capture pair and one HTTP 500 carrying SQLSTATE 23505. A 200-iteration sequential test passes, and a 50-thread version passes on a laptop but fails on the production-sized cluster. Explain why, and give the fix.
Approach
- Read the 23505 as evidence, not as noise. A unique violation on the INSERT proves two requests both passed the SELECT and both reached the INSERT, which means both had already called the processor. The duplicate charge happened before the constraint fired. The constraint is reporting the race; it is not causing it, and anyone who treats the 500 as the bug fixes the wrong thing.
- Name the interleaving precisely. Under READ COMMITTED each statement takes a fresh snapshot, so two concurrent requests with the same key can both run the SELECT before either INSERTs and both see zero rows. Raising the isolation level does not fix check-then-act by itself, because at SELECT time the first transaction has written nothing to conflict with; SERIALIZABLE only converts the race into a 40001 abort that the code must then retry.
- Explain the reproduction gap rather than calling the bug rare. The window is the duration of the processor call: milliseconds against a stub on a laptop, hundreds of milliseconds against a real processor. Production retries are also correlated, since a client timeout produces a second request at a predictable delay, while a thread-pool test fires all 50 within microseconds and lands them on the same side of the window. The local test is not exercising the window at all.
- Restructure so the database picks the winner before any side effect. INSERT the key first with ON CONFLICT (scope, key) DO NOTHING RETURNING id. A returned id means this request owns the effect and may call the processor. No returned row means another request owns it, and note that RETURNING yields nothing on conflict, so the loser must then SELECT the existing row explicitly. Mutual exclusion now lives in one atomic statement and the window is gone.
- Give the loser something to read. If the winner is still in_progress, the loser must neither error nor perform the effect: it polls the row inside the caller's timeout budget and replays response_status and response_body once status is completed, or returns 409 when request_fingerprint differs. Without this, deduplication turns a successful payment into a visible failure.
- Close the crash window separately, because the atomic insert does not cover it. If the winner dies after calling the processor and before writing completed, the row stays in_progress with a stale locked_at. Recovery must query the processor for that key or client reference rather than assume either outcome, which is why the processor's own idempotency key has to be the same value, generated once by the caller and reused on every attempt.
Follow-up
- The same key arrives with a different request_fingerprint. What do you return, and why is returning the cached response wrong?
- What is your locked_at staleness threshold, and what does the sweeper do when it finds an expired one?
- Write the test that fails on the laptop. What do you have to inject to make the window observable there?
For a candidate senior enough that the loop turns on design and judgement rather than on whether the coding round gets finished. Five days build one system properly and then stress it; coding gets a single maintenance day, on the assumption that the risk at this level is an unexamined tradeoff rather than a missed algorithm.
Prepare, practise & reflect
One practical outcome each day. Spend longer where you need it.
0 / 7 done01Multi-level class design: the banking ledger
- Build the reported banking ledger in levels: create accounts; deposit, withdraw and transfer, each returning an explicit failure result; scheduled payments; top accounts by activity. Finish and test each level before starting the next
- Repeat the pattern on the bank's multi-level task manager or in-memory cloud storage problem, keeping entities in dictionaries keyed by id
- Write down which level-1 choices made later levels easy and which forced changes
Deliverable: Two multi-level implementations with tests for each level, plus a short list of design choices that survived every later level.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02In-memory stores: TTL, eviction, snapshots and locks
- Implement the in-memory key-value database with TTL expiration and snapshots. Store the expiry with each value, treat a key as missing once the current time reaches its expiry, and decide whether a snapshot copies state or records versions
- Solve TTL Cache with Eviction using a hash map plus a min-heap keyed by expiry, skipping stale heap entries for keys that were overwritten
- Implement the file system class with FILE_UPLOAD, FILE_GET, FILE_COPY and lock/key checks. Test copying onto an existing name and access with the wrong key
Deliverable: A TTL store with snapshot support, a bounded TTL cache, and a file system class, each with edge-case tests.
Practice prompt ↗Practice prompt ↗03API traversal and timestamped lookups (the phone-screen patterns)
- Solve URL Maze with Error Handling and Clue-Driven HTTP Sequencing with a requests-style client: visited set, bounded retries with backoff for 5xx, timeouts, 429 and 408 (honouring Retry-After), no retry on other 4xx, explicit exit check
- Solve API Interaction With Hashmap and DFS, visiting each endpoint once
- Solve the flight-records questions: get_user_location(time) with per-user sorted events and binary search, and get_user_with_most_flights with a counter. Settle the 'in the air' case and ties out loud
- Pair with someone, or record yourself, and narrate assumptions before each function
Deliverable: Working HTTP traversal code with a written retry policy, and a tested flight-records solution that states its complexity.
Practice prompt ↗Practice prompt ↗04Data processing and SQL
- Convert snake_case tokens to camelCase across a sentence, preserving punctuation and leading or trailing underscores. Test tokens that are all underscores and tokens with numbers
- Aggregate transaction totals by minute bucket by flooring each timestamp to its minute. Handle empty input and out-of-order records
- Work the bank's Recurring Weekly Spend and Optimizing SQL Query Performance questions, then do this guide's worked SQL exercise on multi-currency amounts and unbalanced transactions (drill-sql-2)
Deliverable: Tested string and bucketing functions, and a SQL balance check that you actually ran against a small fixture.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Application and interface engineering
- Frontend or fullstack track: build the spreadsheet with formula dependencies. Keep a dependency graph, recompute dependents in topological order and reject cycles
- Build the calendar day view in React: sort events by start time, group overlapping events, and assign columns so overlapping events sit side by side
- Build Wordle or tic-tac-toe with state held in one place and derived values computed rather than stored
- Backend track: spend the day on a second multi-level problem and the bank's Implement a Clean In-Memory Transaction Ledger instead
Deliverable: One complete interface build (or backend equivalent) that runs, with a note on how its state is structured.
Practice prompt ↗Practice prompt ↗06System design: money movement and rate limiting
- Design the corporate card transaction pipeline: authorization, settlement events, fraud signals and notifications. Name where duplicates and out-of-order events arrive and how idempotency keys stop them
- Design and implement a sliding-window rate limiter per user, then explain what changes when it runs across several servers
- Work this guide's settlement-ingestion design exercise (drill-design-4), then the idempotent charge endpoint (drill-sql-1) and the duplicate-capture debugging question (drill-debugging-5)
Deliverable: A written pipeline design with its failure modes and consistency choices, and a working rate limiter.
Practice prompt ↗Practice prompt ↗07AI-assisted coding, behavioral stories and a full mock
- Build a small data-processing module with an AI assistant under a self-imposed prompt cap, explaining each generated block out loud and fixing its bugs yourself
- Prepare a story for each reported behavioral prompt: your proudest project, a project that fell behind, a disagreement with leadership or product, how you use and verify AI, and a customer pain point or incident
- Do this guide's worked coding exercise on per-account balances (drill-coding-3) as a mock under a timer, narrating as you would to an interviewer
- List your questions and constraints for the recruiter: track, level, round formats, tool policy
Deliverable: A recorded AI-assisted session you can explain line by line, five behavioral stories with fixed project facts, and one completed mock.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
The source notes say the onsite includes a behavioral interview with a hiring manager. The reported prompts cover ownership, trade-offs and business impact, a schedule slip, disagreement with leadership or product, AI in your daily workflow, and customer pain points or incidents. For each one, prepare one specific story: the decision you made, the evidence behind it and the outcome. Keep the project facts consistent with anything you described in a design round.
Tell me about the project you are most proud of: what was your specifi…
Tell me about the project you are most proud of: what was your specific ownership, what trade-offs did you make, and what was the business impact?
Approach
- 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.
- Pick a story where you made the decision, not one where you watched it.
Follow-up
- How did you know your change caused the improvement?
- What would you do differently if you ran that again?
How have you navigated a complex customer pain point or technical inci…
How have you navigated a complex customer pain point or technical incident in the past? What would you do differently in hindsight?
Approach
- Name the disagreement and how you resolved it with evidence.
- Give the blast radius: what could have broken, and what you measured.
- Close with what you would do differently, concretely.
Follow-up
- How did you know your change caused the improvement?
- What did you decide not to do, and why?
Force an implicit timeout behaviour into an explicit decision
The risk decision service has an 80 ms p99 budget inside a roughly 2 s caller timeout. Today, when its feature store is unavailable, the timeout handler returns approve. Nobody chose that; it is what the code does. You need a real decision: fail open, fail closed, or refer, potentially differing by amount band. Describe a time you turned an accidental behaviour into an owned decision. State who had to be in the room, the data you brought, what you did when nobody wanted to own it, and where the decision was recorded so it outlived you.
Approach
- The probe is whether you can drive a cross-functional decision rather than escalating and waiting. Lead with the framing that makes it undeniable: this is already a product decision, it is currently being made by an exception handler, and the only question is whether anyone reviews it.
- Bring the two losses side by side instead of arguing a principle. Fail open costs expected fraud loss on approved-but-should-have-declined volume during the outage; fail closed costs declined good payments, which is lost revenue plus customer harm and a support queue; refer costs manual review capacity, which is a headcount number and saturates within minutes at 3,000 decisions per second. Give each as a rate per minute of outage using real volume.
- Propose the banded answer as the default, because the two losses cross over at an amount: below some threshold the expected fraud loss is smaller than the expected decline loss, above it the reverse, and the crossover is computable from observed fraud rate by band. That converts a values argument into an arithmetic one.
- Name the attendees by the decision they own, not by title: whoever carries fraud loss, whoever carries approval rate, and whoever staffs manual review. Three people who can each say yes is a decision; eight people who can each say no is a meeting.
- Say what you did when ownership was contested. A strong answer has a forcing function: propose a default in writing with a review date and state that it ships unless someone objects, which converts inaction into consent rather than into another meeting.
- Record it where the code can find it: the decision, its date, its owner, the amount thresholds, and a test asserting the fallback behaviour, so the next engineer reading the timeout handler learns it was chosen. A wiki page nobody links from the code is the generic answer.
Follow-up
- The feature store is degraded rather than down and the model is scoring on stale features. Is that the same decision?
- How do you stop the banded thresholds from silently rotting as fraud patterns shift?
- Nobody objects to your written default, and six months later there is an outage and a loss. Who owns it?
- 01
Tell me about the project you are most proud of: what was your specific ownership, what trade-offs did you make, and what was the business impact?
- 02
Describe a time when a project you were leading fell behind schedule. How did you realign stakeholders, reprioritize scope, and drive execution?
- 03
Describe a situation where you had a strong technical disagreement with engineering leadership or product managers. How did you approach the conversation and reach alignment?
- 04
How do you integrate AI into your daily development workflow, and how do you evaluate and verify the accuracy of AI-generated output?
- 05
How have you navigated a complex customer pain point or technical incident in the past? What would you do differently in hindsight?
Is this an official Ramp interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Ramp. The rounds and questions reflect what candidates have reported, not a process Ramp has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗How hard is the Ramp Software Engineer interview?
The source notes describe the loop as rigorous and focused on practical execution rather than obscure algorithm puzzles. Expect production-style problems, API navigation and multi-part software built under time limits, with complete, fully passing solutions expected in coding stages. Prepare by finishing problems end to end and testing them, not by collecting puzzle patterns.
PracHub interview research ↗Can I use my own IDE and documentation during coding rounds?
The source notes report that in most technical rounds candidates can use their own editor or IDE, consult official language documentation and run code locally, unless the interviewer says otherwise. Formats change, so confirm with your recruiter and practise in the setup you will actually use.
PracHub interview research ↗How does the AI-assisted coding round work?
The source notes describe access to an AI assistant in some technical rounds, with a cap on the number of prompts. The notes add that interviewers ask candidates to explain line by line how the generated code works and why particular data structures were chosen. To practise, build a small data-processing module with a self-imposed prompt limit and explain each block out loud as you go.
PracHub interview research ↗How long does the process take?
The source notes give roughly three to five weeks from first contact to offer, and elsewhere three to four weeks. They report that recruiters usually give stage updates within days. Ask your recruiter for the schedule of your own loop.
PracHub interview research ↗Is there a system design round?
The source notes list system design among the onsite's technical rounds and describe design rounds as aimed at backend and senior candidates. Those rounds cover ledgers, transaction pipelines, event-driven processing and consistency. Reported design questions include a corporate card transaction pipeline and a sliding-window rate limiter. Ask the recruiter whether your loop includes one.
PracHub Software Engineer practice ↗Do I need to know React?
The reported questions include React builds such as a calendar day view, a spreadsheet with formula dependencies, an email client and a Wordle game. The source notes list React as a nice-to-have for fullstack and frontend roles. If your track is backend, confirm with the recruiter before investing heavily. If it is frontend or fullstack, practise building one of these end to end.
PracHub Software Engineer practice ↗Which programming language should I use?
Use the language you write fastest and most correctly. The source notes list Python, TypeScript/JavaScript, Go and Java as examples of expected proficiency. The HTTP maze questions are described with a requests-style client, which maps naturally onto Python.
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