Brex sells corporate cards, business banking, global wire payments and travel and expense management as one financial platform for businesses. The source notes for this guide place Software Engineers across that stack: payment and transaction pipelines, backend microservices, customer-facing web interfaces and workflow automation. Named areas include the Task Workflows Platform, the transaction authorization engine, and the integration of enterprise HRIS systems into the identity architecture. Problem areas listed include distributed transaction consistency, low-latency API integrations, multi-currency ledger management and data-driven fraud detection.
For preparation, the domain matters most. The reported questions are about money moving and spend data. In coding, you check whether a player can afford a card from gem balances, aggregate spend from a REST endpoint, and flag suspicious transactions by shared attributes. In design, you authorize card transactions and build ledgers for peer-to-peer transfers and gift cards. The SQL bank asks for transaction counts, monthly totals and consecutive-day patterns. Practise these practical domain problems before any abstract algorithm drills.
The sources also describe two formats worth practising on their own: a debugging exercise, where you get an existing codebase with failing tests and fix it, and a values interview that can include live role-play. Prepare for each separately instead of treating them as ordinary coding and behavioural rounds.
Recruiter Call
reportedCandidates describe a first conversation with a technical recruiter about background, expectations and role fit. Use it to learn what comes next. Ask whether your technical screen is a live call or an online practical assessment, which modules the virtual onsite includes (candidates report practical coding, debugging, system design and a values interview), and what environment the debugging exercise expects. Describe your scope in concrete terms: the systems you owned end to end and any payments, ledger or transaction work, because that is the material the later rounds draw on.
What to demonstrate
- Whether your background and expectations fit the role as the recruiter understands it
- Whether you can explain your most relevant work clearly and briefly, especially services that handle transactions or money
How to prepare
- Ask whether the technical screen is live or an online assessment, and which languages and tools it allows
- Ask which onsite modules you will have and whether the debugging exercise runs in your own local environment
- Prepare a short account of two systems you owned end to end, including the failure you were responsible for fixing
- Settle your compensation expectation and its split before the call so you can give a number when asked
Technical Screening
reportedCandidates report this as either a live technical call or an online practical coding assessment focused on data structures, domain modeling or API integration. The reported coding prompts match that description. One is a card-and-gem purchase engine that grows through can_purchase, purchase and colour discounts. Another fetches transactions from a REST endpoint and computes monthly totals, peak months or merchant streaks. A third matches flagged transactions by shared attributes. The sources do not say which of these appear in the screen itself, so practise all of them in both formats. For a live call, talk through the code as you write it. For an automated assessment, test against the given examples and the cases they leave out.
What to demonstrate
- Whether your domain model survives an extension, such as adding purchase and discounts to an affordability check, without a rewrite
- Whether you handle real API data correctly: pagination, nested JSON, ISO-8601 timestamps and time zones
- Whether the code runs and has been checked against edge cases such as zero balances, missing fields or an empty response
How to prepare
- Build the gem engine in three passes (affordability, then purchase with state updates, then per-colour discounts and wild gems), and reuse one effective-cost function throughout
- Write a script against any public paginated JSON API that follows every page and computes a monthly total and a longest consecutive-day streak
- For the automated format, write a small harness first that runs the given examples plus empty and single-record inputs, and prints expected against actual output
Virtual Onsite Loop
reportedThe source describes the virtual onsite as several focused modules run by senior engineering team members. Candidates can take it in one day or split it across two consecutive days. The reported evaluation areas are practical live coding and API integration, debugging an existing codebase against failing tests, distributed systems design for financial workloads, and a values interview that can include role-play. Each one needs a different approach. In coding, finish and test. In debugging, read before you edit. In design, start from requirements and failure modes. In the role-play, hold a live conversation instead of reciting a story.
What to demonstrate
- Debugging: whether you read failing assertions and stack traces before changing code, and fix root causes without breaking existing API contracts
- Design: whether you bring up idempotency, double-entry ledgers, locking and double-spend prevention in flows such as card authorization or peer-to-peer transfers
- Values: whether you communicate directly, show ownership and negotiate a trade-off with the people in a role-play
- Coding: whether you finish working, tested code for practical prompts such as API consumption or domain state logic
How to prepare
- Build a small multi-file repo with planted bugs (off-by-one day-of-week index, missing leap-year rule, wrong holiday-override precedence) and practise fixing it from the failing tests alone
- Install and verify your language runtime, SDK and test runner on the machine you will use before the day
- Design the card authorization engine and a peer-to-peer transfer service end to end, and name your idempotency, ledger and locking choices before anyone asks
- Run a role-play mock where a partner plays a product manager pushing a feature date against your technical-debt fix
7 candidate reports. Individual accounts describe a particular role and hiring cycle.
Brex Software Engineer interview delayed for months before I took another offer
My process stretched on for months and felt completely disorganized. The recruiter sometimes couldn't get a response from the hiring team for more than a week, so I was left waiting without any real momentum. The interview steps never lined up cleanly because of the delays. What I remember most is the lack of updates and the way the timeline kept slipping. By the time anything finally moved, I'd…
Read full experienceBrex Software Engineer interview with debugging and high pressure system design
I went through a recruiter call and then several technical rounds. The whole process felt hostile and disrespectful of my time. Even when the interviewers were outwardly neutral, I didn't feel much respect for the effort involved in sitting through multiple steps. The hardest part was that I never got clear feedback about why I was rejected, so I was left guessing where things went wrong. The tec…
Read full experienceBrex Software Engineer interview: recruiter call under 15 minutes
I applied and quickly received an invitation for a screening call, so the timeline moved fast. The process ended with a rejection shortly afterward, although the screening itself was fairly standard. The recruiter call lasted under 15 minutes. We went through the usual prompts: telling me about myself, describing a project or complex feature I had worked on, and explaining how I approached it. Th…
Read full experienceBrex Frontend Engineer interview with interrupted live coding
I started with an interview that felt straightforward and respectful, and the recruiter seemed involved and supportive. Then I moved into a technical coding interview where the interviewer repeatedly required me to talk while coding. I found that counterproductive. The constant interruptions made it easy to lose focus and added anxiety to an already stressful live coding environment. I was trying…
Read full experienceBrex Account Executive interview with mock cold-call rounds
My process with Brex didn’t feel smooth, even though it started in a fairly normal way. I went through the usual early screening setup, but the scheduling and follow-through immediately gave me a strange feeling. One calendar invite was outside the availability I’d provided. When I asked questions beforehand, they were mostly brushed off. On the day of the interview, the interviewer was late and…
Read full experiencePracHub editorial advice for the preparation topics above.
Editing code in the debugging exercise before reading the failing tests
Candidates describe a repository with failing unit and integration tests. The reported bugs are in places like day-of-week indexing, leap-year rules, holiday overrides and state mutation. Run the suite first, read each failing assertion and stack trace from top to bottom, and state the root cause before you touch any code. Fix the smallest thing that explains the failure and re-run everything after each fix. Do not change function signatures or response shapes, because the reported task is to restore passing tests without breaking existing API contracts. Install and verify your runtime, SDK and test runner beforehand so setup does not eat into the exercise.
Writing can_purchase in a way that forces a rewrite when purchase and discounts are added
The reported card-and-gem prompt grows in stages: first affordability, then a purchase that updates state, then discounts for each card colour you hold. Bank variants add wild or gold gems that can cover a shortfall. Keep player state explicit, with gem counts by colour and held cards by colour. Compute the discounted cost per colour in one function that both can_purchase and purchase call. In purchase, validate everything before changing anything, so a failed purchase leaves state untouched. Clamp discounted costs at zero, and spend coloured gems before wild gems. Test these cases: an exact balance, one gem short but covered by a wild gem, and a discount larger than the cost.
Getting timestamps and date windows wrong in spend aggregations
Reported prompts ask for total monthly spend, peak months and consecutive-day merchant streaks from a REST endpoint, and the SQL bank asks for similar aggregations. Follow pagination until the endpoint says there are no more pages. Parse ISO-8601 timestamps into timezone-aware values and say which zone defines a month or a day. Handle missing or malformed records instead of crashing. For streaks, reduce the data to one row per merchant per day before looking for consecutive dates, so two purchases on the same day do not count as a two-day streak. Check month and year boundaries such as January 31 to February 1, and keep amounts as integer minor units in every sum.
Designing a payment flow without idempotency or a ledger
Reported design prompts include a card authorization engine that answers card-network webhooks within a tight latency bound, a peer-to-peer transfer service, a gift card and rewards ledger, and a workflow engine driven by spend events. Bring up correctness without waiting to be asked. Cover an idempotency key per authorization or transfer, enforced by a unique constraint. Use double-entry ledger entries that sum to zero, and row locks or conditional updates on balances. Decide, and say, what authorization returns when a dependency is slow. A timeout is an unknown outcome, so reconcile with the other side before you retry. Store amounts as integer minor units together with the currency code.
Telling a story in the values role-play instead of negotiating inside it
The source describes role-play scenarios in the values interview. One is a priority conflict between delivery timelines and technical debt, played out with two interviewers. Stay in the scene. Ask what each side needs, restate their concern, and put a concrete risk on the debt. Then offer a specific split, such as shipping a guarded scope now and scheduling the fix with an owner and a date. Finish by saying what you would communicate and to whom. Rehearse aloud with a partner playing the other side, because a prepared STAR answer does not carry over to a live exchange.
Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.
Card Game & Gem Engine: Implement a `can_purchase` function to determi…
Card Game & Gem Engine: Implement a can_purchase function to determine if a player can afford a card given their current gem balances (e.g., red, green, blue). Extend this with a purchase function that updates state, and introduce a discount mechanism where holding cards of a specific color reduces future purchase costs for that color.
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?
Mathematical String Evaluation: Implement a function that parses and e…
Mathematical String Evaluation: Implement a function that parses and evaluates string-based mathematical expressions containing operations and parenthesis (e.g., evaluating "5 times (20 plus 30)").
Approach
- Restate the input: its shape, its size, and what is guaranteed about it.
- Walk one small example through your approach before writing the whole thing.
- Choose the data structure from the access pattern, not from familiarity.
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?
Attribute Matching & Similarity: Given a list of flagged transaction e…
Attribute Matching & Similarity: Given a list of flagged transaction entries with multiple metadata attributes (such as user, location, and merchant), compare candidate entries and flag suspicious activity based on attribute matching thresholds ($k$ common attributes).
Approach
- 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.
- 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?
Answer as-of balance queries over an append-only entry log
Given 400 million ledger_entry rows (entry_id, account_id, direction, amount_minor, currency, business_date) and 2 million queries of (account_id, currency, as_of_date) asking for the balance at the end of that business date, produce every answer. The obvious solution — per query, sum that account's entries with business_date <= as_of_date — is correct. Say precisely why it will not finish, then give one that will, with time and space complexity. Corrections are posted as new entries carrying their own business_date.
Approach
- Cost the naive version in numbers before rejecting it. Spread uniformly over 20 million accounts, each query touches about 20 rows behind a per-account index and 2 million queries is 4e7 row touches — perfectly fine. The problem is skew: one pooled clearing or merchant settlement account holding 3e7 entries, taking 10% of the queries, is 6e12 row touches. Name the skew; 'n is large' is not the reason.
- The structural fact that buys a cheap answer: entries are append-only and never updated, so a prefix sum over an account's entries ordered by
(business_date, entry_id)is stable — nothing behind position i can change. No mutable-balance design offers that, and it is why the storage is worth paying for. - Offline sweep, when all queries are known up front: externally sort entries by
(account_id, currency, business_date, entry_id)and queries by(account_id, currency, as_of_date), then merge-walk both with a running sum, emitting each query's answer as the sweep passes its date. O((n + q) log(n + q)) dominated by the sort, O(1) beyond sort buffers, one sequential pass over each input instead of 2 million random seeks. - Online alternative: materialise end-of-day snapshots — one row per
(account_id, currency, business_date)that had activity, holding the cumulative total. A query becomes one index seek for the latest snapshot at or beforeas_of_date, O(log n) per query, over far fewer rows than n. Use snapshots when queries arrive singly and the sweep when they arrive as a batch. - Corrections are the subtlety: an entry posted today but dated back changes historical answers, so every snapshot for that account from that date forward is stale. Either keep a Fenwick tree over dates per account (O(log D) update and prefix query) or recompute that account's snapshots from the corrected date onward. Then be precise about what reproducibility means — yesterday's statement is reproducible as of a stated snapshot time, not identical forever.
- Bound the resources: int64 sums throughout, no float; 400 million rows at roughly 48 bytes of the columns you actually need is about 19 GB, so the sort is external and its fan-out is chosen from the sort buffer, not from the row count.
Worked solution 40 min
- Compute both costs explicitly: the uniform case at about 4e7 row touches, and the skewed case at about 6e12. Showing that arithmetic is the answer to 'why'.
- Implement the offline sweep on a 10-million-row, 50,000-query fixture, merging on
(account_id, currency, business_date, entry_id). - Implement the naive version as the reference answer and assert both agree on every fixture query.
- Add a correction entry dated 30 days back, re-run, and assert that exactly the queries with
as_of_dateon or after that date move, all by the same signed amount. - Measure rows touched and wall time for each at 10 million rows, then extrapolate to 400 million and state the assumption that makes the extrapolation valid — sequential I/O, no random seeks.
Follow-up
- One account holds 30% of all entries. What does the external sort do with it, and what would you do for that one key instead?
- Queries now arrive online at 500 per second. Which design survives, and what does keeping the other one warm cost?
- A correction lands with a
business_date90 days back. Which snapshots are now wrong, and how does a reader find out?
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?
Version a loan schedule instead of soft-deleting posted instalments
loan_instalment is keyed by (loan_id, schedule_version, instalment_no) and carries due_date, principal_minor, interest_minor, fee_minor, paid_principal_minor, paid_interest_minor, status, days_past_due, effective_from (date) and superseded_at (timestamptz). A borrower defers two payments on 2026-03-14, and instalments 1 to 6 already have allocations posted against them. Model exactly what the deferral writes, and write the query that returns the schedule as the borrower saw it on an arbitrary date. Say why stamping the old rows with deleted_at, or updating them in place, fails an audit.
Approach
- Treat the deferral as an insert, not an edit: write a complete new schedule_version with effective_from = the deferral instant on 2026-03-14, and in the same transaction stamp superseded_at on every row of the outgoing version with that identical instant, so the two version windows are half-open and adjacent rather than overlapping. Instalments 1 to 6 are reproduced unchanged, because they are what the borrower was told and what was posted to the ledger.
- Write the as-of read as a version selection, not a row filter: WHERE loan_id = $1 AND effective_from <= $2 AND (superseded_at IS NULL OR superseded_at > $2), then assert that exactly one schedule_version comes back - COUNT(DISTINCT schedule_version) = 1, not one row - so an overlapping window raises rather than silently returning two interleaved schedules under one instalment_no.
- Fix the type mismatch before writing that predicate: effective_from is declared date and superseded_at timestamptz, so comparing them casts the date at the session TimeZone and two readers in different zones select different versions near midnight. Put both columns in one domain, timestamptz, keep the window half-open with effective_from inclusive and superseded_at exclusive, and resolve a bare as-of date to an instant once, in the loan's booking timezone, at the edge of the system.
- Say what deleted_at loses. It records that a row stopped being current but not what replaced it or from when, it leaves every downstream query obliged to remember deleted_at IS NULL, and one query that forgets double-counts the schedule. Versioning puts the same information in the primary key where it cannot be forgotten.
- Close the arithmetic: under the loan's stated day-count convention the new version must still sum to outstanding principal plus scheduled interest to the minor unit, with the per-period rounding residual placed in one named instalment, conventionally the last, rather than smeared across the tail.
- Index (loan_id, effective_from DESC) for the as-of lookup, keep superseded versions online rather than archiving them, and enforce with a trigger that no UPDATE touches a row whose paid_principal_minor or paid_interest_minor is non-zero.
Worked solution 25 min
- Insert a 12-instalment version 1 with effective_from at origination, then allocate payments against instalments 1 to 6.
- Apply the deferral: insert version 2 effective at the 2026-03-14 deferral instant, reproducing instalments 1 to 6 byte for byte and re-amortising 7 to 12, and set superseded_at on all twelve rows of version 1 to that same instant in the same transaction.
- Write the as-of query with the version-selection predicate and run it for instants resolved from 2026-03-01 and 2026-03-20 in the loan's booking zone, and for the deferral instant itself.
- Compare SUM(principal_minor) per version against the original principal and locate the rounding residual.
Follow-up
- What does days_past_due mean for an instalment that exists in two versions with different due_dates?
- A payment arrives allocated to an instalment_no that exists only in the superseded version. What do you do with it?
- How do you prove the ledger postings made under version 1 still reconcile once version 2 exists?
Gift Card & Rewards Ledger: Design a scalable architecture for issuing…
Gift Card & Rewards Ledger: Design a scalable architecture for issuing, redeeming, and auditing gift cards and corporate rewards points across global enterprise clients.
Approach
- Choose a partition key and say what query it makes expensive.
- State the consistency you need, and where you are willing to be stale.
- Name the failure you are designing for, then the recovery path.
Follow-up
- What breaks first when traffic grows ten times?
- What would you drop to keep the system up under load?
Credit Card Authorization Engine: Design an end-to-end transaction pro…
Credit Card Authorization Engine: Design an end-to-end transaction processing system that receives webhooks from card networks (e.g., Mastercard), verifies account balances, applies spending rules/limits, and responds with an approval or decline in under 100 milliseconds.
Approach
- Fix the scope first: who calls this, how often, and what they do when it fails.
- Name the read and write paths separately; they rarely have the same bottleneck.
- Name the failure you are designing for, then the recovery path.
Follow-up
- How does this behave when that dependency is down for an hour?
- What would you drop to keep the system up under load?
Task Orchestration Infrastructure: Design an asynchronous workflow eng…
Task Orchestration Infrastructure: Design an asynchronous workflow engine that triggers dynamic multi-channel notifications, approval routing, and third-party SaaS integrations based on enterprise spend events.
Approach
- Name the read and write paths separately; they rarely have the same bottleneck.
- Name the failure you are designing for, then the recovery path.
- State the consistency you need, and where you are willing to be stale.
Follow-up
- What would you drop to keep the system up under load?
- How does this behave when that dependency is down for an hour?
Fan out ordered events to fifty thousand merchant endpoints
Deliver signed events to 50,000 merchant endpoints, at least once, preserving order per destination, retrying with backoff out to 24 hours. Peak is 20,000 events/s with a long tail: most destinations take under one event per minute, a few take thousands per second, and at any moment some are dead or answering in 30 seconds. Design the delivery layer: the partition key, how order is preserved, the concurrency bound, and how one 30-second destination is stopped from delaying the other 49,999. State where backpressure is applied.
Approach
- The ordering guarantee is per destination, so the partition key is destination_id, not event id or aggregate id. That much is forced. What it does not solve is the tail: hash destinations onto a fixed pool and a single 30-second destination adds up to 30 seconds of latency to every destination sharing its partition, which is head-of-line blocking wearing a partitioning key as a disguise.
- Separate scheduling from partitioning: keep a per-destination queue plus a next_attempt_at row, and have workers claim a destination under a lease rather than pull from a shared event queue. Order comes from allowing at most one in-flight request per destination; parallelism comes from the number of distinct destinations claimed at once. Worker count stays bounded and independent of the 50,000 destinations, because an idle destination consumes a row, not a thread.
- Handle the dead ones with a per-destination circuit breaker: after N consecutive failures or timeouts, move that destination to a slow lane with a long poll interval and a small worker share, keeping its events queued and ordered; disable and notify after the 24-hour schedule expires. The retry timer holds the delay, not a blocked worker.
- Accept that a single destination at thousands per second cannot be both strictly ordered and parallel. Either weaken the guarantee to per-aggregate order and partition within that destination by aggregate_id (consumers already order on aggregate_version, so this costs them nothing), or batch several events per request in order and keep one request in flight.
- Apply backpressure at enqueue, per destination: bound queue depth, and past the bound either coalesce event types where only the latest state matters or shed under a documented policy. The outcome to prevent is one destination's 24-hour backlog consuming the storage and IO that the other 49,999 need.
Worked solution 30 min
- Model three destinations: A normal, B answering in 30 s, C normal, each with 1,000 ordered events queued.
- Implement workers that claim a destination under a lease, with at most one in-flight request per destination.
- Measure delivery p99 for A and C while B is stalled, then repeat the run with a shared hashed worker pool for contrast.
- Fail B for 30 minutes and confirm the breaker moves it to the slow lane without dropping or reordering its queue.
Follow-up
- A merchant returns 200 but never processed the event. Whose problem is it, and what do you offer them?
- A merchant asks to replay three days of events. What in this design makes that cheap or expensive?
- How do you rotate the signing secret without a delivery gap?
Backend Service Test Suite: Given a small service with multiple failin…
Backend Service Test Suite: Given a small service with multiple failing unit and integration tests, debug latent concurrency or state mutation bugs to restore full test suite passing status without breaking existing API contracts.
Approach
- Establish what changed and when, before forming any theory.
- Pick a bisection that eliminates candidates whichever way it turns out.
- Separate the trigger from the cause; the deploy is rarely the bug.
Follow-up
- How would you tell a cause from a coincidence here?
- What would you add now so this is faster to diagnose next time?
Holiday Calendar & Date Offset Debugger: Given an existing multi-file …
Holiday Calendar & Date Offset Debugger: Given an existing multi-file codebase designed to compute delivery schedules based on official calendar holidays, identify and fix subtle bugs related to day-of-week indexing, leap years, and holiday overrides.
Approach
- Separate the trigger from the cause; the deploy is rarely the bug.
- Check the instrumentation before believing the symptom.
- Say what evidence would prove you wrong, then go and look for it.
Follow-up
- What would you add now so this is faster to diagnose next time?
- What would you look at first, and what would it rule out?
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 done01Map the loop and set up your tools
- Sort the reported questions into coding, debugging, system design, SQL and values, and mark which ones you have never attempted
- Write the questions for your recruiter call: screen format, allowed languages, onsite modules, and whether debugging runs in your local environment
- Install and verify your language runtime, test runner, HTTP client, JSON parsing and a timezone-aware date library
- Write a short scope summary of two systems you owned end to end
Deliverable: A categorized question list, a recruiter question list, and a working local environment with a passing sample test.
Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗02Card-and-gem purchase engine
- Implement can_purchase from colour gem balances, then purchase with state updates that change nothing when the purchase fails
- Add per-colour discounts from held cards and wild or gold gems that cover any shortfall, reusing one effective-cost function
- Write tests for an exact balance, one gem short but covered by a wild gem, a discount larger than the cost, and an unknown card
- Rebuild it from scratch within a time box while explaining each decision aloud
Deliverable: A tested purchase engine plus a list of the edge cases you would name in the interview.
Practice prompt ↗Practice prompt ↗03REST API consumption and parsing prompts
- Write a script that follows every page of a paginated JSON endpoint and computes monthly spend and the peak month from ISO-8601 timestamps
- Add a consecutive-day same-merchant streak: one row per merchant per day first, then check that the dates are consecutive across month boundaries
- Solve the attribute-matching prompt: flag a candidate that shares at least k attributes with a flagged entry, first by brute force, then with an index keyed on attribute and value
- Build an evaluator for word expressions such as "5 times (20 plus 30)" with correct precedence and parentheses
Deliverable: Three working programs, each with a short note on complexity and the failure cases you tested.
Practice prompt ↗Practice prompt ↗04SQL over transactions
- Write queries for the SQL bank topics: transaction counts, monthly spend totals, same-day transactions across consecutive months, and consecutive-day purchases at one merchant
- Practise the similarity query: count the attributes each candidate shares with a flagged entry and filter on a threshold
- Work through the worked exercise "Answer as-of balance queries over an append-only entry log" and check its answers against a naive reference
Deliverable: A query file covering each SQL topic, plus your completed as-of balance exercise.
Practice prompt ↗Practice prompt ↗Worked solution ↗05Debugging an unfamiliar codebase
- Build or borrow a small multi-file service with tests, and plant bugs: an off-by-one day-of-week index, a missing leap-year rule, wrong holiday-override precedence, and a shared mutable default
- Fix them using only the failing tests: run the suite, read assertions and stack traces, state the cause, apply the smallest fix, and re-run everything
- Add one bug caused by a null response or a missing error handler in a transaction pipeline, and fix it without changing any public signature
Deliverable: A bug log recording, for each bug, the failing test, the root cause, the fix and the evidence that nothing else broke.
Practice prompt ↗Practice prompt ↗06Payments system design
- Design the card authorization engine: webhook intake, balance check, spending rules and limits, and the response inside the prompt's latency bound, including what happens when a dependency is slow
- Design a peer-to-peer transfer service with double-entry ledger entries, idempotency keys and a locking strategy, using the "Make a charge endpoint safe under concurrent duplicate retries" drill for the key-claim path
- Sketch the gift card and rewards ledger or the spend-event workflow engine, then work through "Fan out ordered events to fifty thousand merchant endpoints" for delivery and backpressure
Deliverable: Two designs taken to schema and failure-mode depth, with idempotency and ledger decisions written next to each.
Practice prompt ↗Practice prompt ↗07Values role-play and a full mock sequence
- Prepare STAR stories for critical feedback, fixing an unowned problem outside your scope, a decision made with incomplete requirements, and a project that missed its target
- Run a live role-play with a partner who plays the other side of a feature-date versus technical-debt conflict, and reach an agreed plan while staying in the scene
- Run a coding mock, a debugging mock and a design mock back to back, and note where you used the wrong approach for the round
Deliverable: Four rehearsed stories, notes from the role-play, and a short list of fixes from the mock sequence.
Practice prompt ↗Practice prompt ↗Worked solution ↗Expand any day for tasks and deliverables. Your progress is saved on this device.
The source describes the values interview as more than standard behavioural questions, often with interactive role-play. Prepare stories that name a person, a decision and a result you can put a number on. Also practise the live format: in a role-play you speak to interviewers in character, so rehearse listening, restating their concern and offering a concrete trade-off.
Handling Constructive Feedback: Describe a project where you received …
Handling Constructive Feedback: Describe a project where you received critical feedback on your architecture or implementation, how you processed it, and what changed in your execution.
Approach
- Name the disagreement and how you resolved it with evidence.
- Close with what you would do differently, concretely.
- Pick a story where you made the decision, not one where you watched it.
Follow-up
- What would you do differently if you ran that again?
- What did you decide not to do, and why?
Own the postmortem for a duplicate-capture incident
A processor slowed down, callers timed out and retried without reusing their idempotency key, and 412 captures were duplicated over 90 minutes before a reconciliation break report surfaced it. Take the on-call role. Describe an incident you owned of comparable blast radius: how it was detected, how you bounded the affected population, what you stopped first, and how customers were made whole. Give a wall-clock timeline, the query or metric that sized the damage, and the change that would have prevented it. Include what you got wrong during the response, not only after it.
Approach
- The probe is whether you can bound an unknown blast radius under time pressure. Open with the invariant that broke (at most one capture per authorisation attempt) rather than the symptom, because the invariant tells the listener what to count.
- Size the population with a stated query, not an adjective: duplicate captures are ledger_entry rows with source_type='capture' grouped by source_id having count(*) > 1, joined back to payment_intent for the affected merchants and amounts. Say how long that query took and whether you could run it against a replica while the incident was live.
- Separate mitigation from fix and say which you did first. Mitigation is usually cheap and blunt (disable the retry path, drop the caller's concurrency, hold captures behind a flag); the fix is a UNIQUE constraint plus a stored response, and it is not an incident-window change.
- State the remediation arithmetic explicitly: refunds are new customer-visible movements with their own fees and their own settlement lag, so the count of duplicates, the total minor units, the refund posting date and the customer notification are four separate numbers a strong answer has ready.
- Close on the prevention change and its cost. Naming one guard that would have caught it earlier (a break-age alert, a duplicate-capture counter on the ledger write path) beats listing five that nobody staffed.
- Name your own error inside the response window: a mitigation you tried that made it worse, or the 20 minutes you spent on the wrong hypothesis. Interviewers weight that heavily because it is the part candidates rehearse away.
Follow-up
- The retry came from a client you do not control. What do you change so a client that regenerates its key per attempt cannot cause this again?
- How would you have detected it in 5 minutes instead of 90, and what would that detector cost in false pages per week?
- A merchant disputes your count of affected transactions. What do you show them?
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
Role-play: two interviewers play out a priority conflict between a product delivery date and reducing technical debt. Reach an agreement with them in character.
- 02
Describe a project where you received critical feedback on your architecture or implementation, how you processed it, and what changed in your execution.
- 03
Tell me about an unowned system failure or operational bottleneck outside your scope that you took on and drove to resolution.
- 04
Describe a critical technical decision you made with incomplete product requirements or changing business constraints.
- 05
Tell me about a technical project that failed or missed its target metrics. What did you learn, and how did you adapt?
- 06
Describe an incident you owned: how you sized the affected population, what you stopped first, and what change would have prevented it.
Is this an official Brex interview guide?
No. It is PracHub's own research and practice material for the Software Engineer role at Brex. Rounds and questions reflect what candidates have reported, not a process Brex has published, and they change over time. Confirm the current format and scope with your recruiter.
PracHub interview research ↗What programming language should I use during the technical rounds?
The source notes report that candidates can generally use a modern language they know well, and name Python, Java, Go and TypeScript. Confirm the allowed languages with your recruiter. For API-parsing and live coding prompts, a language with little boilerplate, such as Python or JavaScript, saves time on HTTP calls and JSON handling. Whatever you choose, know its HTTP client, JSON parser and date library well enough to use them without looking them up.
PracHub interview research ↗Are LeetCode-style algorithmic puzzles common in Brex interviews?
The reported questions are mostly practical: modeling a card-and-gem purchase system, consuming a REST API and aggregating spend, fixing bugs in an existing codebase, and designing payment systems. One reported prompt, evaluating an expression such as "5 times (20 plus 30)", is closer to a classic parsing problem, so keep stack-based or recursive-descent parsing ready. Spend most of your practice on domain modeling and API work rather than puzzle drills.
PracHub interview research ↗How is the debugging round structured?
Candidates describe getting a repository of existing code with a failing test suite. The task is to understand the business logic, isolate the bugs and fix them until the tests pass. Reported examples include a holiday calendar that computes delivery schedules, with bugs in day-of-week indexing, leap years and holiday overrides, and a small service with concurrency or state-mutation bugs. Set up and verify your runtime, SDK and test runner before the interview.
PracHub interview research ↗What is the typical timeframe for the hiring process?
Reports put the process at roughly three to five weeks, and the source notes also mention two to four weeks, depending on scheduling and team matching. Ask your recruiter for the current timeline.
PracHub interview research ↗What is the values interview like?
The source describes it as going beyond standard behavioural questions, often with interactive role-play. In one reported scenario, two interviewers play out a priority conflict between shipping a feature and reducing technical debt. Prepare STAR stories about feedback, ownership outside your scope, and decisions made with incomplete requirements. Also practise talking to people live instead of narrating a story.
PracHub Software Engineer practice ↗Should I prepare SQL for this role?
Yes. The question bank for this role includes SQL items on transaction counts, monthly spend totals, same-day transactions across consecutive months, consecutive-day purchases at the same merchant, and similarity matching over suspicious entries. The sources do not tie these to a specific round, so treat SQL as a category to cover: GROUP BY aggregation, date truncation, self-joins and window functions.
PracHub Software Engineer practice ↗Can the virtual onsite be split across days?
The source says candidates can take all the onsite rounds in a single day or split them across two consecutive days. Choose based on how you manage energy. If you split them, put the modules you find hardest on the day you expect to be freshest.
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