Revolut · Software Engineer
Updated · 2026-09-24

Revolut Software Engineer
Interview Guide

THE 60-SECOND BRIEF

Revolut runs banking, trading, crypto and payment services. Software Engineers there are reported to work on core banking features, risk and fraud detection pipelines, distributed ledgers and payment gateways. Reported backends are mostly Java, Kotlin and Scala on transactional databases such as PostgreSQL. The reported interview questions follow that stack closely: thread-safe money movement, transaction isolation and locking, and designs that must stay correct when a dependency fails.

This guide covers the four stages candidates report for the Revolut Software Engineer role (Initial Screening, Hands-on Technical Validation, Theory Questions, System Design Round) and the four question categories behind them: concurrency and multi-threading, database mechanics and SQL, system architecture and design patterns, and coding fundamentals with test-driven development. The practice material leans toward backend correctness problems, such as idempotent writes, lock contention and ledger design, because that is what the reported questions ask for.

Revolut candidates report 4 rounds · ≈ 3-5 weeks. The stages below are what candidates describe, not a published process.

Reconcile the ledger against processor settlement filesMake every money-moving endpoint idempotent by keyModel money movement as balanced double-entry postings

40 min read

Practice 17 Software Engineer prompts
4Company bank questionsSnapshot · Sep 24, 2026 PT
18Candidate experiences ↗Read their reports
17Practice promptsAcross five skill areas
3With worked solutionsIncluded in the practice prompts

A Software Engineer at Revolut builds backend systems for banking, trading, crypto and payment products. Candidate reports put the work in core banking features, risk and fraud detection pipelines, distributed ledgers and payment gateways. The reported stack is Java, Kotlin and Scala backends on transactional databases such as PostgreSQL. The reported questions focus on thread safety, ledger correctness and data isolation.

The reported technical questions lean toward practical backend problems rather than abstract puzzles. Coding examples include an in-memory banking service that rejects invalid transactions, a thread-safe money transfer, and a load balancer with Random and Round Robin selection. The reported database questions go deep on PostgreSQL isolation levels, optimistic versus pessimistic locking, and index choice. The reported design questions are about banking systems: booking against unreliable third-party APIs, distributed transactions, and reliable event publishing.

Reported rounds expect working code, tests and modular design, not pseudocode. Aim your preparation there: finished, tested solutions to money-movement problems, and theory answers that name the exact anomaly or failure a mechanism prevents.

01

Initial Screening

reported

This stage is only described as an initial screening to assess candidate fit, so the reports do not say what it covers. Prepare for the two things a screen can end on. The first is logistics that surface late: start date, notice period, location and work authorisation. The second is a clear, short account of your backend experience. The later stages are described as live coding, theory questions on databases and concurrency, and banking-domain design, so use this call to confirm which language you will code in and what the live coding environment looks like. The hands-on stage is described as coding in your own IDE, and knowing that early leaves time to get it ready.

What to demonstrate

  • Whether your background and the role's backend focus line up. Be ready to name the languages, databases and concurrency work you have actually shipped.
  • Whether hard constraints such as start date, notice period, location and authorisation are compatible before technical rounds are scheduled

How to prepare

  • Write a short summary of one backend system you built where correctness under concurrency or failure mattered. Cover what it did, what could go wrong, and what you did to prevent it.
  • Ask the recruiter which language you can use for live coding, whether you code in your own IDE, and whether tests are expected. Write down the answers.
  • List your constraints and your compensation range as one-line facts before the call, so you are not working them out live.
PracHub interview research ↗
02

Hands-on Technical Validation

reported

This stage is described as live coding on real-world backend scenarios, writing code in your own IDE. The sources do not say which questions are asked here, but the reported coding-category questions are the right practice set for it: an in-memory banking service with deposits, withdrawals and transfers that rejects invalid transactions atomically, a Minesweeper-style board generator, a custom Set built without Java collections, hash tables or trees, and a load balancer with Random and Round Robin selection. The source's tip for live rounds is complete, working code with tests (TDD) and modular design, not pseudocode. If the interviewer asks whether you want to add more validations or tests, treat it as a prompt to go looking for edge cases. Avoid two time sinks: coding before a failing test exists, and making random fixes to a failing case you have not isolated.

What to demonstrate

  • Whether the code runs and is covered by unit tests you wrote as you went, not added at the end
  • Whether the design stays modular, with the domain (accounts, transactions, balances) kept apart from input handling
  • Whether invalid inputs are rejected explicitly and atomically, such as a negative amount, overdraft, unknown account or transfer to the same account
  • Whether randomness is testable, such as a seeded or injected random source so the output is deterministic under test

How to prepare

  • Before the round, configure your IDE with a test runner and a project template that compiles and runs one passing test, so setup costs you nothing
  • Build the in-memory banking service test-first: write a failing test for each rejection rule before the code that enforces it, and keep amounts in BigDecimal or integer minor units
  • For the mine grid, inject the random source and assert invariants (exactly k mines, every count equals its mined neighbours) rather than exact layouts. Place k mines with selection sampling so no extra array is needed.
  • Rehearse a thread-safe Round Robin selector using an AtomicInteger counter and Math.floorMod, so the index stays valid after the counter overflows
PracHub interview research ↗
03

Theory Questions

reported

This stage is described as targeted theory questions on databases and concurrency. The sources do not say which questions belong to it, so prepare from the two reported categories that match. The reported database questions cover PostgreSQL isolation levels (Read Committed, Repeatable Read, Serializable) and the anomalies each allows, optimistic versus pessimistic locking, B-Tree versus BRIN indexes on high-volume ledger tables, and sharding, partitioning and replication; the source also lists MVCC as an area to be ready on. The reported concurrency questions cover Java thread safety beyond global synchronized blocks, race conditions on shared caches, and deadlock-free transfers, and each can be answered as theory as well as code. Short answers that name a mechanism without its failure mode do not hold up to follow-up questions. For each mechanism, say what it prevents, what it still allows, and what it costs.

What to demonstrate

  • Whether you can map each PostgreSQL isolation level to the anomalies it prevents and allows, including that its Repeatable Read is snapshot isolation that still permits write skew, and that Serializable needs a retry on SQLSTATE 40001
  • Whether you can say when SELECT ... FOR UPDATE beats a version-column optimistic check, and what each does under high contention
  • Whether you know the JVM primitives (synchronized, ReentrantLock, ReadWriteLock, atomic variables, concurrent collections) and when each is the cheapest correct choice
  • Whether index answers are tied to access patterns, for example BRIN relies on physical order matching the column, such as an append-only timestamp

How to prepare

  • Build a grid with isolation levels as rows and anomalies (dirty read, non-repeatable read, phantom, serialization anomaly) as columns, fill it in for PostgreSQL, and explain each cell aloud
  • Reproduce a lost update in two psql sessions under Read Committed with SELECT then UPDATE, then fix it three ways: an atomic conditional UPDATE, SELECT ... FOR UPDATE, and a version column
  • Write a two-account transfer that deadlocks with naive locking, then fix it by locking in ascending account id order. Be ready to explain tryLock with a timeout as the alternative.
  • Explain B-Tree versus BRIN for a ledger table in three sentences: size, which queries each serves, and why BRIN cannot back a uniqueness constraint
PracHub interview research ↗
04

System Design Round

reported

This round is described as focused on real-world banking domain challenges rather than abstract concepts. The sources do not tie specific questions to it, but the reported design-category questions are the practice set: an apartment booking system that integrates with unreliable third-party APIs without double bookings, a URL shortener with distributed caching and high availability, a card ordering feature, a high-throughput ledger with strict ordering and idempotency, multi-region banking data synchronisation, and conceptual questions on SAGA versus Two-Phase Commit, the Transactional Outbox with Kafka, and DDD, CQRS and Event Sourcing for a ledger. The same themes recur: every external call can fail or repeat, so correctness has to come from idempotency keys, local transactions and compensation rather than hoping the call succeeds once.

What to demonstrate

  • Whether you pin down the invariant first, for example no double booking or no double spend, and show where in the design it is enforced
  • Whether failures of third-party calls are handled explicitly: timeouts, retries with idempotency keys, compensating actions and reconciliation
  • Whether you can compare SAGA and 2PC, and explain why an outbox row written in the same local transaction avoids the dual-write problem
  • Whether trade-offs are stated and justified, for example consistency versus availability across regions or read models split from write models under CQRS

How to prepare

  • Walk the apartment booking design end to end: local reservation hold, idempotent call to the partner API, confirmation or compensation, and a reconciliation job for unknown outcomes
  • Explain the Transactional Outbox from write to consumer: business row and outbox row in one transaction, a relay that publishes to Kafka, at-least-once delivery, consumer deduplication by event id
  • Compare an orchestrated saga with 2PC on the same transfer, covering who holds locks, what happens when the coordinator dies, and what a compensation looks like
  • Work through the drill 'Raise the write ceiling on one hot clearing account' to practise stating a throughput ceiling as a number before proposing a design
PracHub interview research ↗

18 candidate reports. Individual accounts describe a particular role and hiring cycle.

Product Manager

Revolut Product Manager interview: hypothetical business case

HR Screen → OtherOutcome: rejected

My process felt lighter than the intense multi-round processes I had seen elsewhere. It started with an HR screen and moved into a case-style evaluation. Recruiter interactions were straightforward, prep materials were provided, and I was expected to do structured analysis. For the case, I worked through a business scenario and gave reasoning and a recommendation. The examples were hypothetical r…

Read full experience
Operations Manager

Revolut Operations Manager Interview Experience: a structured process with late red flags

Take-home Project → OtherOutcome: offer

My process was long and structured: a recruiter screen, a cognitive-style test, a home task, a case interview, a bar raiser, and a team-fit stage. The recruiter did a fair amount of preparation between rounds and kept things moving, although there were hiccups. Interviews could start more than 10 minutes late without much notice. The bar raiser was much shorter than I expected. Parts of the proce…

Read full experience
Software Engineer

Revolut Software Engineer interview: distributed systems and opaque system design

Technical ScreenOutcome: rejected

The process started smoothly with a recruiter screen and technical rounds rooted in practical distributed-systems patterns. I cleared several early stages, but I did not get through the system design interview. That round was difficult because I could not tell what the interviewer wanted me to emphasize or how quickly to move through the discussion. The earlier coding and technical work was concr…

Read full experience
Software Engineer

Revolut Software Engineer concurrency and database interview experience

HR Screen → Technical Screen

The interviews centered on backend fundamentals: concurrency, databases, and how transactions behave under pressure. The process began with an HR round that included technical scenarios rather than staying purely behavioral. I was asked about concurrency and isolation, and we discussed database topics such as locking, CQRS, sharding, and indexes. Later technical interviews focused on production-r…

Read full experience
Operations Manager

Revolut Operations Manager Interview Experience: take-home case rejected before deadline

HR Screen → Online Assessment → Take-home Project → Other

The process had a recruiter screen, an online assessment, a live case interview, and then a week-long take-home business case. The assignment felt like substantial unpaid work: it involved a JIRA workflow, process maps, SQL queries, and a full fraud-detection analysis. I was rejected while I was still finishing the take-home, before its deadline. That made the process feel disorganized or dishone…

Read full experience

PracHub editorial advice for the preparation topics above.

01

Writing the implementation first and adding tests at the end, or not at all

Reported live rounds expect test coverage written TDD-style. Start with one failing test for the simplest rule, make it pass, then add a failing test for each rejection rule (negative amount, overdraft, unknown account, self-transfer) before the code that enforces it. For random output, inject a seeded source and assert invariants rather than exact values.

02

Naming an isolation level without the anomalies it still allows

PostgreSQL defaults to Read Committed, where every statement takes a fresh snapshot, so a SELECT-then-UPDATE on a balance loses updates under concurrency. Its Repeatable Read is snapshot isolation: it aborts the conflicting writer with SQLSTATE 40001 but still permits write skew across two rows, which only Serializable closes. Both stronger levels need a bounded retry loop on 40001. Say which anomaly each level stops and which it does not.

03

Locking the two accounts of a transfer in call order

Transfers A to B and B to A running together each hold one lock and wait for the other. Always acquire locks in a fixed order, such as ascending account id, in Java code and in SQL alike (on the database side, PostgreSQL reports the deadlock as SQLSTATE 40P01). Mention tryLock with a timeout as the alternative and what it costs: retries and possible starvation.

04

Holding money in double or a hard-coded two-decimal format

Binary floating point cannot represent 0.1 exactly, so repeated arithmetic drifts and equality checks fail. Use BigDecimal with an explicit scale and rounding mode, or integer minor units with the currency's exponent carried alongside it, since ISO 4217 exponents are 0 for JPY, 2 for most currencies and 3 for BHD or KWD. State the one place rounding happens.

05

Designing as if a third-party or cross-service call happens exactly once

In the booking, ledger and outbox questions, assume every external call can time out with an unknown result and every message can arrive twice. Show the idempotency key, the local transaction that records intent, the compensation path, and the reconciliation job that resolves unknown outcomes. Name where the no-double-booking or no-double-spend invariant is enforced.

Choose a category, try a prompt, then open its approach, worked solution or follow-up when you need it.

14 technical prompts3 include a worked solution

How do you structure unit tests using TDD to test functions that gener…

medium
data structures and algorithms

How do you structure unit tests using TDD to test functions that generate non-deterministic or random output?

Approach
  1. Choose the data structure from the access pattern, not from familiarity.
  2. State the target complexity and say which constraint rules the naive version out.
  3. 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?

How do you choose between using primitive data types versus arbitrary-…

medium
data structures and algorithms

How do you choose between using primitive data types versus arbitrary-precision types like BigDecimal when handling multi-currency balances?

Approach
  1. Name the brute-force solution and its complexity before improving on it.
  2. State the target complexity and say which constraint rules the naive version out.
  3. Walk one small example through your approach before writing the whole thing.
Follow-up
  • How does this change if the input no longer fits in memory?
  • What is the worst case, and how likely is it on real data?

Write a program to generate a grid matrix filled with randomly placed …

medium
data structures and algorithms

Write a program to generate a grid matrix filled with randomly placed mines while maintaining an optimal space complexity.

Approach
  1. State the target complexity and say which constraint rules the naive version out.
  2. Walk one small example through your approach before writing the whole thing.
  3. Restate the input: its shape, its size, and what is guaranteed about it.
Follow-up
  • Which test case would catch an off-by-one here?
  • What is the worst case, and how likely is it on real data?

What mechanisms would you use to handle race conditions when writing t…

medium
languages, concurrency and fundamentals

What mechanisms would you use to handle race conditions when writing to a shared cache or state across multiple worker threads?

Approach
  1. Name what is shared across threads and what owns each piece of state.
  2. Say what the runtime actually does before reasoning about the code.
  3. Reach for the cheapest primitive that closes the race, not the broadest lock.
Follow-up
  • How would you prove the race exists rather than suspect it?
  • Where could this allocate more than you expect?

How do you ensure thread safety in Java without relying entirely on gl…

medium
languages, concurrency and fundamentals

How do you ensure thread safety in Java without relying entirely on global synchronized blocks?

Approach
  1. Say what the runtime actually does before reasoning about the code.
  2. Reach for the cheapest primitive that closes the race, not the broadest lock.
  3. Identify the window where an invariant is briefly untrue.
Follow-up
  • Where could this allocate more than you expect?
  • What happens if two callers reach this at the same time?

Compute peak held exposure from overlapping authorisation holds

mediumWorked solution
sweep lineintervalsauthorisation holds

An account has up to 2 million authorisations on one business date: (auth_id, amount_minor, created_at, expires_at) with the hold live over the half-open interval [created_at, expires_at), plus capture events (auth_id, captured_minor, captured_at) that reduce the hold at captured_at, and explicit reversals that drop the remainder to zero. Timestamps are microsecond-precision timestamptz. Return the maximum total held amount across the day and the earliest instant it is reached, with complexity. Then say what changes if the deliverable is the peak per minute instead.

Approach
  1. Expand each authorisation into signed delta events rather than reasoning about intervals: +amount at created_at, -remaining at expires_at, -captured_minor at each captured_at, -remaining at reversed_at. The problem collapses to a running sum over a sorted event list.
  2. Sort the 2n to 4n events by (timestamp, sign) with negative deltas ordered first on a tie. The half-open convention forces that: at exactly expires_at the hold is already gone, so a - must land before a + at the same instant or you report a one-microsecond peak that never existed. O(n log n) time, O(n) space.
  3. Sweep once, tracking running, best and best_at, taking the first instant that attains the maximum. Say out loud which tie rule you are using — 'the peak' is ambiguous when the same level is reached twice, and the caller needs to know which instant they are being handed.
  4. If timestamps are bucketed (1,440 minute buckets for the per-minute variant), drop the sort for a difference array: add the delta at the start bucket, subtract at the end bucket, prefix-sum once. O(n + B) time and O(B) space, strictly better, at the cost of answering only at bucket resolution.
  5. Assert the invariant during the sweep: running must never go negative. A negative total means a capture exceeded its authorisation, which is an invariant violation upstream rather than a sweep bug — fail loudly instead of clamping at zero and reporting a plausible number.
  6. Handle carry-in: a hold created before the window contributes its remaining amount as the sweep's initial value, not as a + event inside the window. Omitting that is the off-by-a-day that makes the first minute of every day look artificially quiet.
Worked solution 25 min
  1. Write the event expansion and the comparator first; the comparator is the part that is wrong in most first attempts.
  2. Fixture A: two holds of 10,000 minor units where the first's expires_at equals the second's created_at.
  3. Fixture B: one hold of 10,000 with a partial capture of 4,000 at t+1 and expiry at t+2, so the held series is 10,000 then 6,000 then 0.
  4. Fixture C: a hold opened the previous day and still live at the window start; seed running with its remaining amount.
  5. Shuffle the events in all three fixtures before sorting and re-run, proving the answer depends only on the comparator.
EXPECTED RESULTA peaks at 10,000 at the first hold's `created_at`, not 20,000. B peaks at 10,000 at t. C's peak includes the carried-in hold. `running` is never negative in any fixture and returns to 0 at the end of A and B.
Follow-up
  • An incremental authorisation raises an existing hold after the fact. Where does that event go, and does it disturb the tie rule?
  • You now need the peak for 10 million accounts inside a nightly window. What changes, and what must the partitioning key be?
  • The peak sizes a funding transfer. Does the business date or the timestamp decide which day that transfer lands on?

For someone who has spent the last few years shipping features and reading other people's code, and who has not solved a timed problem from a blank file in a long time. Five days rebuild the primitives and the patterns that sit on them, working from invariants rather than remembered solutions, and the last two attach that back to the rest of the loop.

Small steps. Visible outcomes.0 / 7 completed
ONE WEEK · YOUR PACE

Prepare, practise & reflect

One practical outcome each day. Spend longer where you need it.

0 / 7 done
01Set up the IDE and build the banking service test-first
  • Configure your IDE with a test runner and a template project that compiles and runs one passing test, so live-coding setup costs nothing
  • Build an in-memory banking service with create, deposit, withdraw and transfer, writing a failing test for each rejection rule before the code that enforces it
  • Decide between BigDecimal and integer minor units for balances, and write two sentences defending the choice for multi-currency accounts

Deliverable: A tested banking service where every invalid transaction is rejected atomically and leaves balances untouched.

Practice prompt ↗Practice prompt ↗Practice prompt ↗Worked solution ↗
02Coding fundamentals: random output, custom structures, load balancing
  • Generate a mine grid with an injected random source, placing k mines by selection sampling, and test invariants (exactly k mines, correct neighbour counts) rather than layouts
  • Implement a Set of integers without Java collections, hash tables or trees, for example a sorted array with binary search, and state the cost of add, contains and remove
  • Implement a load balancer with Random and Round Robin selection behind one interface, with a seeded random source for tests

Deliverable: Three solutions with tests, each with its time and space complexity written above the main method.

Practice prompt ↗Practice prompt ↗Practice prompt ↗
03Concurrency: transfers, shared state and lock choice
  • Make the Day 1 transfer thread-safe with per-account locks acquired in ascending id order, then run a stress test of opposing transfers and assert total money is conserved
  • Make the Round Robin selector thread-safe with an AtomicInteger and Math.floorMod, and explain why a synchronized method would also be correct but slower under contention
  • For a shared cache written by several worker threads, compare a synchronized map, ConcurrentHashMap.compute and a ReadWriteLock, and say when each is the cheapest correct choice

Deliverable: A stress test that fails with naive locking and passes with ordered locking, plus a one-page note on JVM concurrency primitives.

Practice prompt ↗Practice prompt ↗Practice prompt ↗
04Database theory: isolation, locking and indexes
  • Fill in a PostgreSQL grid of isolation levels against anomalies and explain each cell aloud
  • Reproduce a lost update in two psql sessions, then fix it with an atomic conditional UPDATE, SELECT ... FOR UPDATE and a version column
  • Work the drill 'Make a charge endpoint safe under concurrent duplicate retries' and explain B-Tree versus BRIN for a ledger table in three sentences

Deliverable: Session transcripts showing the lost update and each fix, and short spoken answers on isolation, locking and index choice.

Practice prompt ↗Practice prompt ↗Worked solution ↗
05Databases under load: contention, scaling and incidents
  • Work the drill 'Raise the write ceiling on one hot clearing account', stating the throughput ceiling as a number before any design
  • Compare sharding, partitioning and replication for a write-heavy banking database: what each scales and what each costs in consistency
  • Work the debugging drill on authorisation p99, writing the diagnostic checklist in order before reading the cause

Deliverable: A written ceiling calculation, a scaling comparison table, and an ordered diagnostic checklist.

Practice prompt ↗Practice prompt ↗
06System design: external APIs, distributed transactions and events
  • Design the apartment booking system with unreliable third-party APIs end to end, marking where double booking is prevented
  • Explain the Transactional Outbox with Kafka from local write to deduplicating consumer
  • Compare an orchestrated saga with 2PC on one transfer, and sketch a ledger using CQRS and Event Sourcing

Deliverable: One full booking design and two short written explanations you can deliver aloud in five minutes each.

Practice prompt ↗Practice prompt ↗
07Timed rehearsal of all four stages
  • Solve one coding question from Day 2 in 45 minutes with tests, working in your own IDE and narrating as you go
  • Answer ten database and concurrency theory questions aloud, one or two minutes each, naming the anomaly or failure each mechanism prevents
  • Run one 45-minute banking design from Day 6 on a new prompt, such as a card ordering feature, and rehearse your screening summary and constraints

Deliverable: A timed coding solution with tests, a list of theory answers that needed a second attempt, and one recorded design walkthrough.

Practice prompt ↗Practice prompt ↗Worked solution ↗

Expand any day for tasks and deliverables. Your progress is saved on this device.

The sources do not describe a separate behavioural stage, but the reported question bank includes ownership and planning questions, such as preventing double-withdrawal incidents and planning an observability overhaul. Prepare stories where you owned a correctness problem end to end, with the specific change that followed.

Reverse a sharding decision after production contradicted it

medium
shardinglock contentionreversibility

To raise throughput past a single row's lock ceiling, you shard a hot settlement account balance into 16 sub-rows. Two weeks later the floor check has to sum all 16 under a stronger isolation level, contention has moved rather than gone, and operations cannot explain the balance to an auditor. Describe a decision you reversed. State what you believed when you made it, the measurement that changed your mind, how you unwound it without causing a second incident, and how long you waited before concluding the data was real rather than noise.

Approach
  1. The probe is whether you can hold a belief loosely and unwind your own work without ego. Begin with the reasoning that was correct at the time: a single balance row commits at roughly one write per lock hold, so at a 4 ms hold you get about 250 writes per second regardless of core count, and sharding is the standard answer to that ceiling.
  2. Name what the original reasoning missed rather than calling it a mistake in general. The floor predicate was a single-row CHECK before sharding and became a cross-row predicate after it, so every write now either sums the shards under SERIALIZABLE with a bounded retry on 40001 or locks them in a fixed order to avoid 40P01. The throughput gain is real but smaller than 16x, and the auditability cost was never priced.
  3. Give the measurement that decided it, with a before and an after: committed writes per second, p99 write latency, retry rate on 40001, and the time an analyst needs to reconstruct one balance. A reversal justified by feel is the generic answer.
  4. Describe the unwind as a migration, not a revert: shadow the consolidated balance, reconcile it against the sum of shards over a full business day including the cutoff, cut reads over first, then writes, keeping the shards readable until one full reconciliation cycle has passed clean.
  5. State the waiting rule you used before acting. Two weeks of a moving p99 can be a deploy or a traffic shift; a strong answer names the signal that separated a trend from noise, such as the retry rate persisting across a low-traffic weekend.
  6. Close with what you would keep. Some of the work is usually salvageable (the instrumentation, the lock ordering, the measured ceiling), and saying which parts survived shows the reversal was analysed rather than abandoned.
Follow-up
  • You still need the throughput. What is the next thing you try, and what does it cost the floor check?
  • How do you reconcile the sharded balance against the consolidated one during the migration without double counting entries posted mid-cut?
  • What would you have measured before the original change that would have made the answer obvious?

Force an implicit timeout behaviour into an explicit decision

medium
fail openrisk decisioningdecision records

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
  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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?

Unblock an engineer on double-posted interest accrual

easy
mentoringidempotent batchaccrual

An engineer two years into their career has a nightly accrual job that double-posts interest for some accounts whenever the batch is partially re-run after a failure. They have spent two days on it and are now rewriting the batch runner. You have 30 minutes. Describe how you have unblocked someone without taking the keyboard: the question you asked first, how you chose between handing over the answer and handing over the method, what you left behind so the next person does not get stuck here, and how you knew they were unblocked rather than deferring to you.

Approach
  1. The probe is whether you grow people or absorb their work. Open with the diagnostic question rather than the solution: ask what identifies one unit of work, because the answer reveals immediately that accrual is keyed by (account_id, accrual_date) and that the job has no uniqueness on it.
  2. Redirect from the runner to the write. The rewrite is aimed at never re-running, which is unachievable; the property needed is that re-running posts nothing new, enforced by a unique index on (account_id, accrual_date) or by passing the same idempotency key to the ledger posting operation so the second attempt is a no-op rather than a second transaction.
  3. Choose deliberately between answer and method and say why. Two days in and blocked on the wrong layer is usually the moment to hand over the framing (restartable at account granularity, idempotent per unit) and let them write the code, because the lesson is the framing and the code is the easy part.
  4. Leave an artefact, not a conversation: a test that re-runs one account twice and asserts one posting, plus two lines in the runbook stating that per-account work must be idempotent because the batch is always partially re-run.
  5. Check that they are unblocked by asking them to predict the failure that the fix does not cover, such as a mid-run rate change producing two different correct amounts for the same key. If they can find the next edge themselves, they own it; if they ask you to confirm each step, they are deferring and you have hidden the block rather than removed it.
  6. Say what you deliberately did not do. Not fixing it yourself before the standup is the whole exercise, and a strong answer names the pressure it resisted.
Follow-up
  • The unique index rejects the re-run, but the first run posted the wrong amount. How should the job behave now?
  • How do you tell whether you taught them or just unblocked them, a month later?
  • The same engineer is blocked again next week on a similar problem. What does that tell you about your first intervention?
  • 01

    Tell me about a payment-critical or data-integrity incident you owned. What broke, how did you find the cause, who did you bring in, and what did you change so it could not happen again?

  • 02

    You have nine months to overhaul observability for a set of backend services. What do you deliver first, what do you defer, and how do you show progress along the way?

  • 03

    Describe a design trade-off you made under time pressure. Which alternative did you reject, and what would have made you choose it instead?

  • 04

    Tell me about a test you wrote that caught a bug before production. What made you write that test?

  • 05

    Describe a technical decision you later reversed. What did you believe at the time, and what measurement changed your mind?

PracHub interview preparation framework ↗
Is this an official Revolut interview guide?

No. It is PracHub's own research and practice material for the Software Engineer role at Revolut. Rounds and questions reflect what candidates have reported, not a process Revolut has published, and they change over time. Confirm the current format and scope with your recruiter.

PracHub interview research ↗
How difficult are the technical interviews at Revolut?

The coding problems are reported as generally medium in algorithmic difficulty. The bar comes from tight time limits and strict criteria on code quality, TDD, concurrency and production readiness.

PracHub interview research ↗
Which programming language should I use during live coding?

Java and Kotlin are reported as the main backend languages and are recommended for live coding. You can generally use another language you are comfortable with, provided you can show solid concurrency handling and TDD. Confirm with your recruiter before the hands-on stage.

PracHub interview research ↗
What is the main point of failure for candidates in technical rounds?

Reported failure points are rushing to write code without setting up tests, ignoring edge cases, failing to explain concurrency trade-offs, and lacking depth on database isolation levels and locking.

PracHub interview research ↗
How long is the live coding exercise?

Reports say you will often have 30 to 45 minutes to complete a live coding exercise, write unit tests and answer quick theory questions. Practise finishing a tested solution inside 45 minutes.

PracHub Software Engineer practice ↗
What is the typical timeline from the initial screen to an offer?

Reports put it at roughly three to five weeks from first contact to offer. Ask your recruiter for the current schedule.

PracHub interview research ↗
Sources & methodology 3 sources ↗

Official role evidence, timestamped platform data and clearly labeled preparation advice.