Monzo Backend Coding Interview: Choosing Between Take-Home and Pair Programming

Choose Monzo take-home or pair programming with official guidance, an original backend exercise, boundary tests, and a README review checklist.

Author: PracHub

Published: 9/8/2026

Monzo Backend Coding Interview: Choosing Between Take-Home and Pair Programming

September 8, 2026

Quick Overview

Choose between Monzo’s backend take-home and pair-programming options using verified official guidance, clearly dated candidate accounts, and a practical format comparison. Rehearse one original TransferBook interface in both settings, test replay and failure behavior, and prepare a README and code-review explanation that make your design decisions clear.

Backend EngineerFree

Choosing Monzo’s take-home or pair-programming option is a decision about how you demonstrate engineering judgment. Choose take-home if you can protect a bounded work session and explain the result afterward. Choose pairing if a live conversation helps you resolve ambiguity and show incremental progress. Both formats call for readable code, tests, and a defensible design.

This guide focuses on that choice and the backend coding round. For broader practice, use the PracHub Backend Engineer question collection. The exercise below is original preparation material, not a leaked Monzo assignment.

Monzo backend coding preparation: take-home and pair programming lead to the same correctness and tradeoff discussion

What Monzo officially says—and what remains uncertain

Official fact, checked September 8, 2026: Monzo’s current UK Staff Backend Engineer listing includes a take-home task or pair-coding exercise. That establishes a current example of the choice, not a guarantee for every level or location. Confirm your own invitation. Monzo job listing

Official process guidance: Monzo’s March 2025 backend interview article describes a small take-home program followed by a review, or pairing on a supplied interface with automated tests. Take-home instructions request a README covering setup, structure, and tradeoffs; extra functionality earns no bonus. Pairing emphasizes incremental reasoning rather than typing speed, and finishing everything is not essential. Use a familiar supported language and development environment. The article’s overview says one hour for pairing, while its detailed section says 45 minutes. Ask which duration applies to your scheduled session. Monzo’s backend process

Candidate reports: A June 2025 discussion includes a candidate describing take-home work followed by a detailed design discussion. A June 2026 poster describes a take-home followed by a 45-minute discussion. These are individual accounts with different dates and contexts; they do not establish a universal schedule or which option has a higher pass rate. 2025 discussion, 2026 account

Two independent, detailed coding reports from the same hiring cycle were not available in this research. Accordingly, the recommendations below are preparation inferences, not claims about undisclosed scoring or exact questions.

Choose the format you can execute well

Compare your actual working conditions before choosing. “I dislike live coding” is useful information, but a take-home can also go badly if you spend every evening adding unnecessary architecture.

Your constraintTake-home may fit when…Pair programming may fit when…
Available timeYou can reserve focused time and stop at a planned boundary.An appointment is easier than finding several uninterrupted work periods.
AmbiguityYou can record assumptions clearly and avoid silently changing requirements.You think more clearly after a short clarification conversation.
CommunicationYou explain completed code well and can retrace the reasoning.You can narrate decisions while keeping the implementation moving.
Main failure riskYou can resist polishing infrastructure beyond the brief.You can recover calmly from a failing test or unfamiliar API.

This table is a decision aid, not Monzo’s rubric. Try the same small task once under each condition. Judge whether a reviewer could understand the behavior and your reasoning, rather than counting lines written.

For take-home, rehearse a stopping rule: the agreed behavior works, boundary tests pass, and another person can run it. For pairing, rehearse a recovery rule: reproduce the failure, state one hypothesis, inspect the relevant state, then make one change. Neither rule requires flawless first attempts.

Before committing, confirm the deadline or session length, available language, test harness, submission format, and any adjustments you need. Let your available time and working conditions settle a close decision.

Rehearse one interface in both formats

Use this original practice contract for a single-threaded, in-memory TransferBook. Its banking vocabulary makes the consequences easy to discuss, but it does not model Monzo’s production ledger.

The constructor receives valid, nonnegative integer balances in minor currency units. A transfer receives a nonempty string ID, source account, destination account, and positive integer amount. Accounts must exist and differ. Invalid requests raise ValueError without changing state.

A successful transfer moves the amount and records its ID with the request details. Repeating that ID with identical details returns False without another movement. Reusing it with different details raises ValueError. New successful transfers return True. Failed requests do not reserve IDs, so a corrected retry may succeed. Reject booleans as amounts even though Python treats them as integers.

The interface is deliberately small:

class TransferBook:
    def transfer(self, transfer_id, source, destination, amount):
        """Return True for a new transfer, False for an exact replay."""

    def balance(self, account):
        """Return the current integer balance."""

Assume valid account-name and transfer-ID types at the boundary. There is no network, persistence, concurrent access, currency conversion, or overdraft facility. Those omissions make the rehearsal assessable; they are not production design recommendations.

Start with A holding 100 and B holding 20. Use fresh state for each independent row below, except where the row explicitly describes a sequence.

Provided test or sequenceExpected resultWhat it exposes
Transfer t1, A → B, 30True; A=70, B=50Basic movement and conservation
Repeat that exact requestFalse; A=70, B=50Successful replay does not move money twice
Reuse t1 with amount 31 after successError; A=70, B=50ID conflicts cannot silently change meaning
Transfer A → missing CError; A=100, B=20Validation must precede mutation
Transfer A → B, 101Error; A=100, B=20Insufficient funds leave balances unchanged
Fail t2 for 101, then retry t2 for 30Second call succeedsFailure does not consume an ID
Transfer zero, a negative amount, or TrueError; balances unchangedInput rules are explicit

A subtle case belongs in your own added tests: after a successful transfer spends most of A’s balance, replay must still return False. Checking current funds before recognizing an already successful request would reject a valid replay.

The central implementation order should therefore be visible:

request = (source, destination, amount)
if transfer_id in self.completed:
    if self.completed[transfer_id] != request:
        raise ValueError("conflicting transfer ID")
    return False

# Validate amount, accounts, and funds before any balance mutation.
self.balances[source] -= amount
self.balances[destination] += amount
self.completed[transfer_id] = request
return True

This excerpt assumes basic input validation has already run and omits the remaining validation body. It is an ordering sketch, not a complete copy-and-run solution. Explain that ordinary validation failures are atomic under this exercise’s assumptions; this is not a crash-safe transaction or a distributed exactly-once guarantee.

TransferBook practice flow: recognize completed IDs, validate a new request, then update both balances and record success

Use a bounded take-home rehearsal

For a personal rehearsal, choose a 90-minute cap—not an asserted Monzo time limit. Spend roughly the first 15 minutes turning the contract into tests, the next 45 implementing and debugging, and the remaining 30 reviewing the result and writing the handoff. Adjust that practice cap if it teaches you nothing about your actual constraints.

Keep the implementation small enough to review in one sitting. Two dictionaries can represent balances and completed requests. An abstract repository layer adds little to an exercise that explicitly excludes persistence. If you introduce an abstraction, explain the concrete duplication or complexity it removes today.

Your README should function as a review map:

README sectionUseful content for this exercise
RunPython version, exact test command, and required dependencies—or none
ContractInteger minor units, rejected inputs, successful replay behavior, and failed-ID reuse
Design decisionCompleted-request lookup occurs before the funds check so replay survives later balance changes
VerificationNamed tests for missing destinations, conflicting IDs, and unchanged state after errors
LimitsSingle-threaded memory only; request history grows with successful transfers
Next changeIf concurrent calls become a requirement, protect the whole decision and update together

Do a clean handoff check: open a fresh directory or environment and follow only your README. A missing dependency or undocumented working-directory assumption is a useful rehearsal finding.

Then close the editor and explain the code aloud. If you cannot explain why you retained request details instead of only a set of IDs, inspect the conflict test. It provides a concrete reason for the data structure.

Use a pair-programming rehearsal that exposes decisions

A 45-minute practice session is useful because it forces prioritization; it is not a promise about your appointment. Ask a partner to supply the contract and tests, then introduce one ambiguity such as whether failed requests reserve IDs.

First, restate observable behavior: “I will validate before mutating, and an exact successful replay must not move funds again.” Clarify the ambiguity before deciding how to implement it.

Next, build the smallest successful path and run a test. Add one failure path, then replay behavior. Keep your explanations attached to changes: “I’m moving the completed-ID lookup earlier because the replay should not depend on the current balance.” This tells a reviewer more than narrating every keystroke.

When a test fails, avoid editing several branches at once. Suppose missing-destination handling leaves A debited. Inspect the order of validation and mutation, move the existence check, and rerun both the failing case and the happy path. State the invariant the fix restores.

Finish with a short status report: working behaviors, known gaps, and the next test you would add. If the clock ends before conflict handling is complete, describe the missing case precisely. “Some edge cases remain” hides information; “reusing a successful ID with a different destination is not rejected yet” is reviewable.

Defend the design without expanding the assignment

Use a claim, evidence, limitation sequence in the review. For example: “A failed destination lookup cannot debit the source; the missing-account test asserts both balances afterward. This holds for validation failures in this single-threaded model, not process crashes.”

Expect your own practice reviewer to challenge the following decisions:

  • Why integer amounts? They match the defined minor-unit contract and avoid introducing rounding into this exercise.
  • Why retain the full request? A set of successful IDs detects repetition but cannot distinguish an exact replay from conflicting reuse.
  • What happens as history grows? Memory usage grows with successful IDs. Expiry would change replay behavior, so it needs an explicit retention requirement.
  • What changes with concurrency? Separate checks and dictionary writes could interleave. Synchronization must cover the check-and-update operation; adding a lock to only one assignment is insufficient.

These are original review prompts. Answer the extension briefly, then return to the implemented contract. Name the condition that would break your design and the requirement that would justify changing it.

Keep AI and reference-tool rules explicit

Official policy: Monzo’s AI guidance supports preparation and refining your own work, prohibits AI answering live interview questions, and advises checking with the recruiter about task-specific use. Preparation permission does not automatically authorize generated take-home code or an active coding assistant during pairing. Confirm the written rules for your process and arrange any AI-related accessibility adjustment beforehand. Monzo AI guidance

Practice with the tools you will actually be permitted to use. You should be able to explain every submitted line and reproduce the reasoning behind a fix.

Five questions for targeted follow-up practice

These verified PracHub records come from other companies. They are transferable preparation, not reported Monzo interview questions. The two discussion prompts specifically support the take-home review, while the implementation and debugging prompts support both formats.

Practice questionUse it to rehearse
Implement Notification Rate LimiterTurn stateful rules into an interface and keep denied requests from corrupting state.
Find Bugs in an LRU CacheProduce a minimal failing test before changing update or eviction behavior.
Debug and Improve a Load BalancerExplain a debugging hypothesis and verify the resulting correction.
Explain a Difficult Technical DecisionConnect a design choice to constraints and rejected alternatives.
Critique a Recent Engineering Project and Explain What You Would RedoDiscuss improvements without pretending the original work had no limitations.

Choose your format after a rehearsal, then use the Backend Engineer collection to target the weakness you observed: implementing a contract, diagnosing a failure, or defending a decision.

Sources and Further Reading


Comments (0)