cswork / libraryOpen practice workspace

Interview guides · Coinme

Coinme Software Engineer Interview Guide

Coinme Software Engineer interview guide: the three reported rounds, API, wallet and payments questions, behavioral STAR prep and a 7-day plan.

The 60-second brief

Coinme works at the border between traditional finance and digital assets. Candidates describe two product areas for engineers: consumer-facing mobile applications and a Crypto-as-a-Service (CaaS) B2B platform that partners integrate with. The reported topic areas for this role are transaction fulfillment at scale, on-chain transaction orchestration, API-first product design, blockchain signing infrastructure and payments integration for fiat on/off-ramps. As a Software Engineer you would work alongside product, compliance and payments colleagues, and candidates describe owning a feature from architecture through deployment and post-launch monitoring, writing product requirement documents that spell out error states, edge cases and compliance constraints, and advising other teams on how to use the APIs.

This guide is for Software Engineer candidates preparing for Coinme. The requirements candidates describe are 5+ years of software engineering, experience building API-first B2B products, a solid grasp of REST APIs and webhooks, and comfort diagnosing problems from logs and request payloads. Crypto-native infrastructure, treasury management, wallet orchestration tools such as Fireblocks, gas optimization and multi-signer architectures are described as a bonus. The guide covers the three reported stages, how to approach every reported question, and a full structure for the behavioral ones.

Candidates report three stages over about 3-5 weeks: a Recruiter Screen, a Coding Assignment and Meetings with Managers. Some candidates report going from application to offer in as little as two weeks, and the pace varies by department.

Focus areas

  • Transaction fulfillment at scale
  • On-chain transaction orchestration
  • API-first product design

Overview

The reported questions fall into three groups. The first is system and integration work in a money-moving setting: queuing high-throughput transactions without losing consistency, troubleshooting an API integration failure in production, security for a wallet orchestration layer, gas and fee management across several chains, a sandbox for third-party developers, and edge cases in payment processing or KYC flows. The second is experience with REST APIs and scalability. The third is people and judgment: a speed-versus-architecture trade-off, collaboration with a product manager or compliance lead, code review feedback, and a quick pivot after a requirements change. Candidates describe the difficulty as average, with the weight on real architecture and trade-offs rather than algorithm puzzles, so prepare to talk about systems you have built, not to recite solutions.

Five of the eleven reported questions are experience or behavioral questions: REST APIs and scalability, the speed-versus-architecture trade-off, the collaboration story, code review feedback and the pivot. They share one preparation method. Build a small bank of four or five real projects, and for each one write down the decision you personally made, the alternatives you rejected, what you measured and what you would change. The REST question needs concrete mechanics from one API you owned, such as pagination, idempotency keys, versioning, rate limits and webhook delivery. The other four need a clean situation, decision, result structure. This guide gives the structure for each in the question cards below.

The stack candidates mention is REST, webhooks, wallet orchestration (Fireblocks is named as a plus), gas optimization and multi-signer setups, plus KYC/AML checks built into the product flow. If you have not worked on-chain, learn the lifecycle of a transaction from the initial request to on-chain settlement, and be ready to explain where a request can be accepted but not yet confirmed. Candidates are also told to treat documentation as part of the job and to bring two or three questions for their interviewers, so keep a short list of your own, for example how API changes are rolled out to partners or where compliance review sits in a feature's delivery.

The Coinme interview process

Candidates describe a three-stage loop. The reported question list is not split by stage, so the cards below are grouped by what they test, not by where they are asked.

Recruiter Screen

Candidates describe the Recruiter Screen as an opening conversation to align on your background and your interest in the company. Treat it as the place to connect your history to the requirements candidates describe: API-first B2B work, REST and webhooks, and diagnosing issues from logs and payloads. It is also where you can ask what the later stages look like, including whether a coding assignment is part of your loop, and what happens after each stage.

What to demonstrate

  • How your background lines up with API-first, financial-systems work
  • Your interest in this company and in fintech or digital assets
  • Logistics fit such as location and timing

How to prepare

  • Write a short walk-through of your career that puts your API, payments or integration work first, with one outcome you can state for each project.
  • Prepare a specific reason for Coinme and for crypto infrastructure beyond general interest; mention a concrete area such as transaction orchestration or wallet security that you want to work on.
  • Write down what to ask: the later stages, whether there is a coding assignment, and who the meetings will be with.
  • Have your location, notice period and compensation expectations ready so the call stays on your background.

Coding Assignment

Candidates report that for certain roles the loop includes a coding assignment or technical exercise completed on your own time, where the stated purpose is to show coding standards, documentation practices and attention to detail. Ask the recruiter for the format, the deadline and what to submit. Because the area is described as covering code quality, testing strategy for financial transactions and troubleshooting, assume your submission is read as a piece of production-style work, not a puzzle answer.

What to demonstrate

  • Clean, modular, maintainable code
  • Documentation: a reader can run it and understand the decisions
  • Testing approach across unit, integration and end-to-end levels, especially for money movement
  • Attention to detail on edge cases and error handling

How to prepare

  • Write a small REST service end to end with a README that states assumptions, how to run it and what you left out, so you know what a complete submission looks like.
  • Add tests for the failure paths first: a duplicate request, a timeout after the side effect, a partial failure and an invalid payload.
  • Practise reading a JSON payload and a log excerpt to locate the fault, since troubleshooting is a named area.

Meetings with Managers

Candidates describe Meetings with Managers as a series of conversations with hiring managers and technical leads covering fit and technical skill. The reported question list covers both the technical design and troubleshooting questions and the behavioral ones, so prepare both kinds for this stage. Expect to be asked about your past projects in depth, including why you chose a technology over its alternatives, and to explain trade-offs to non-technical listeners such as product and compliance colleagues.

What to demonstrate

  • Technical depth in transaction pipelines, API design and wallet security
  • Judgment and trade-off reasoning, with the why behind decisions
  • Communication across product, compliance and payments roles
  • Fit with a team that works in an agile way

How to prepare

  • Rehearse out loud the design questions on high-throughput transaction queuing and the third-party sandbox, naming the idempotency key, the transaction states and the failure handling in each.
  • Prepare the five behavioral stories from the cards below, each tied to a project you can explain in detail.
  • Build one story about working with compliance, because KYC and AML checks are part of the flows candidates describe.
  • Write two or three questions for each meeting about team challenges and how the platform's APIs reach partners.

Where candidates lose points

Answering the REST and scalability question with a list of terms (caching, load balancers, microservices) and no API you owned

Pick one API and walk its decisions: pagination style, idempotency on writes, error codes, rate limits, versioning and webhook retries. State one measurement from your own work.

Designing the transaction queue, the sandbox or a payment flow for the happy path only

For each design, name the request identity that makes retries safe and separate accepted, pending, failed and confirmed states. Say what happens on a timeout after the side effect and when a downstream dependency is down.

Turning the product manager or compliance story into a complaint about the other function

State their constraint fairly, show the options you offered with their costs, and end with the agreement reached. KYC and AML checks are part of the flows candidates describe, so treat them as design inputs.

Submitting a coding assignment that runs but has no README, tests for the failure paths or recorded assumptions

Candidates report that documentation practices and attention to detail are the point. Include run instructions, the assumptions you made, tests for duplicates, timeouts and bad payloads, and a note on what you would add next.

Naming Fireblocks, multi-signer setups or gas optimization on your CV and being unable to explain them

These are listed as bonus skills, so claim only what you used. For the rest, learn the transaction lifecycle from request to on-chain settlement and say plainly where your experience stops.

Questions & practice

Diff a projection against the primary without per-row point reads

Hard · reconciliation · range hashing · throttling

The listing projection has drifted and some rows show a stale version. The primary holds 40,000,000 resource rows across 12,000 tenants while serving 1,200 writes and 14,000 reads per second. The obvious repair, reading each resource row and comparing its version against the projection, is correct and would eventually finish. Explain precisely why it is unacceptable here, then give a diff that finds the differing rows, state its complexity, and make it safe to run against a live primary. Replication lag is usually under 100 ms and is not bounded.

Approach

  1. Quantify the naive cost rather than calling it slow: 40,000,000 point reads at even 0.5 ms each is over five hours serialised, and the only lever is concurrency, which is exactly what you cannot spend. The primary's pool is sized for the write path, and 40,000,000 random reads evict the buffer cache that sustains the 85 percent cache hit rate, so the audit degrades the system it is auditing.
  2. Replace random access with one ordered pass per side. Both sides can be read in (tenant_id, resource_id) order, which is a sequential scan on each and a merge join in O(n) time and O(1) memory. For a dense diff that is the whole answer, and it reads the primary once instead of 40,000,000 times.
  3. For the expected sparse case, compare range hashes instead of rows: partition the key space, compute per range an order-independent aggregate over hash(resource_id, version), compare aggregates, and descend only into ranges that differ. With d differing rows and branching factor B, at most d ranges mismatch per level, so the drill-down examines O(d log_B(n/d)) ranges and reads full rows only in mismatching leaves.
  4. Aggregate with a sum modulo 2^64 or a multiset hash, never XOR. XOR is order-independent but self-cancelling, so two rows wrong in the same way, or a row duplicated on one side, leave the range aggregate matching and the range is declared clean.

Follow-up

  • The diff reports 900 stale rows. How do you decide between patching those rows and rebuilding the projection from resource_revision?
  • Same job, but the projection lives in a search index that cannot be scanned in key order. What changes?

Track a rolling failure rate per destination for circuit decisions

Easy · sliding window · ring buffer · circuit breaker

The egress service delivers about 1,500 webhooks per second across roughly 40,000 destinations, each call bounded by a 10 second timeout. Maintain, per destination, the failure rate over the trailing 60 seconds so a caller can ask before dispatch whether the circuit should open. Attempts arrive as (destination_id, finished_at_ms, outcome). Requirement: amortised O(1) per attempt, with total memory bounded by the destination count rather than by traffic. Give the structure, its exact memory, and the rule that stops a destination with three attempts from opening a circuit.

Approach

  1. Name the exact-deque version and then reject it as the default. Holding timestamps and advancing a tail pointer past anything older than now minus 60 seconds is a correct two-pointer window at amortised O(1) per attempt, but its memory tracks in-window traffic, so one destination in a retry storm holds hundreds of thousands of entries while thousands of quiet destinations hold none.
  2. Use a ring of 60 one-second buckets per destination, each bucket a pair of counters for attempts and failures. On an attempt, advance the ring by the elapsed whole seconds, zeroing at most min(elapsed, 60) buckets, then increment the head. That is amortised O(1) with a fixed footprint per destination.
  3. State the footprint: 60 buckets times two 4-byte counters is 480 bytes of payload per destination, so 40,000 destinations is roughly 20 to 25 MB with per-entry overhead, bounded by the catalogue rather than by the rate. The cost is granularity, since the oldest bucket ages out in whole seconds, which is far tighter than the decision needs.
  4. Require a minimum sample before the circuit may open. A destination with three attempts and three failures reads as 100 percent and is not evidence; a floor of roughly 20 attempts in the window makes the ratio meaningful, and below that floor use a run of consecutive failures as the trigger instead.

Follow-up

  • The fleet is 30 instances and each sees roughly a thirtieth of a destination's traffic. Where does the rate actually live, and what does a per-instance answer get wrong?
  • A destination answers in 9.5 seconds and succeeds. It is not failing but it is consuming your per-destination concurrency. What signal should open the circuit here?

Collapse a redelivered event batch into per-aggregate high-water marks

Easy · hashing · at-least-once · aggregation

You drain a batch of up to 5,000,000 events, each (aggregate_id BIGINT, aggregate_version INT, event_type, payload). The log guarantees order within one aggregate only; the batch merges 64 partitions, and a relay failover has redelivered a range, so an older version for an aggregate can appear after a newer one. Given a map of last_applied_version per aggregate, produce the events worth applying, at most one per (aggregate_id, version), plus the count discarded. Target O(n) time. State the memory for 2,000,000 distinct aggregates and what you do when it does not fit.

Approach

  1. One pass, one hash map from aggregate_id to the highest version kept, and a discard counter. An event whose version is at or below last_applied_version for its aggregate is dropped without further work, which is the whole reason the event carries its version rather than a delta. O(n) expected time, O(d) space in distinct aggregates.
  2. Keep the maximum, never the last occurrence. The redelivered range means the final appearance of an aggregate in the batch can be an older version than one seen earlier in the same batch, so last-wins applies stale state over newer state and the projection regresses with no error anywhere.
  3. Cost the memory instead of calling it large: an 8-byte key plus a 4-byte version is 12 bytes of payload, and an open-addressed table held at a 0.7 load factor costs roughly 17 bytes per entry before per-slot metadata, so 2,000,000 aggregates is tens of megabytes in a native layout and several times that in a runtime that boxes both key and value.
  4. If the distinct set exceeds memory, partition on hash(aggregate_id) mod P and reduce each partition independently. Every event for one aggregate hashes to the same partition, so the per-partition result is exact and the merge is concatenation rather than a second reduction.

Follow-up

  • The payload is a patch rather than a snapshot, so applying only the highest version loses the intermediate changes. What changes in your reduction?
  • How do you detect that version 7 arrived while version 6 was never delivered, and what should the consumer do about the gap?

Keep soft-deleted accounts from blocking re-registration

Easy · soft delete · unique constraints · engine differences

app_user holds user_id, tenant_id, email CITEXT, password_hash (NULL for SSO principals), email_verified_at, auth_version, status ('invited','active','suspended','deactivated'), created_at, updated_at, deleted_at. Two live accounts for one address inside a tenant must be impossible, but an address freed by a soft delete must be reusable, and the same tenant may delete and re-register it repeatedly. Write the uniqueness DDL for PostgreSQL 16, then the equivalent for MySQL 8 where partial indexes do not exist, and say what each permits once three deleted rows already hold that address.

Approach

  1. Start from what is actually unique: not (tenant_id, email), but (tenant_id, email) among live rows. PostgreSQL says that directly — CREATE UNIQUE INDEX app_user_live_email ON app_user (tenant_id, email) WHERE deleted_at IS NULL. A full constraint over the same two columns burns the address permanently the first time someone deletes an account.
  2. Keep case-insensitivity in the type or the index, never in the application: CITEXT as given, or UNIQUE (tenant_id, lower(email)) as an expression index where the extension is unavailable. A case-sensitive unique column is exactly how two accounts for one human appear.
  3. For MySQL 8 the predicate has to move inside the key: add a discriminator column that is a constant 0 while the row is live and is set to user_id on delete, with UNIQUE (tenant_id, email, deleted_marker). Live rows share the constant and still collide; deleted rows differ from each other and stop colliding.
  4. State the NULL variant and its dependency: leaving the marker NULL for deleted rows also works, because a unique index treats NULLs as distinct — true in MySQL, and true in PostgreSQL only under the default NULLS DISTINCT, which PostgreSQL 15 lets you reverse. Check the polarity against the three existing deleted rows: constant-on-live is what preserves the collision you want, and reversing it silently admits duplicate live accounts.

Follow-up

  • A deleted account re-registers with the same address the next day. Do the old resource rows follow the new user_id, and how does the API keep the two principals apart?
  • How do you honour an erasure request while resource_revision.actor_user_id still references this table?

Write the update path that detects a concurrent edit

Medium · optimistic concurrency · transactional outbox · audit history

resource carries version INT NOT NULL DEFAULT 1. resource_revision holds revision_id, resource_id, version, actor_user_id, change_kind, patch JSONB, request_id, created_at with UNIQUE (resource_id, version). outbox_event holds aggregate_type, aggregate_id, aggregate_version, event_type, payload, status. A PUT carries the version the client read. Write the exact statements for the single transaction that applies the edit, records the revision and enqueues 'resource.updated', and give the handler's branch on zero affected rows. Then say what PostgreSQL 16 does under READ COMMITTED when two of these updates hit one row at once.

Approach

  1. One transaction, three writes, no network call inside it: UPDATE resource SET title = $3, version = version + 1, updated_at = now() WHERE resource_id = $1 AND tenant_id = $4 AND version = $2; then INSERT the resource_revision row at version $2 + 1; then INSERT the outbox_event row at the same aggregate_version. The event goes to a table rather than a broker because no transaction spans both.
  2. Branch on the affected-row count before doing anything else. Zero has three causes — stale version, wrong tenant, row gone — so re-read once and map to 409 carrying the current version, or 404 for an id outside the caller's tenant, which also stops the endpoint confirming that another tenant's id exists.
  3. State the engine behaviour instead of assuming it. Under READ COMMITTED the second UPDATE blocks on the row lock, and when the first commits PostgreSQL re-evaluates the WHERE clause against the newly committed row, so the version predicate now fails and the statement reports zero rows. Under REPEATABLE READ the identical collision raises SQLSTATE 40001 instead, so the handler must fold both shapes into one conflict response.
  4. Keep UNIQUE (resource_id, version) even though the predicate already serialises writers. It is what makes a lost update unwritable if any other path ever reaches the revision table, and it converts a logic bug into 23505 rather than into a silently missing history row.

Follow-up

  • A client sends the version it read ten minutes ago and the resource has moved three versions. What is in your 409 so it can resolve the conflict without a full re-fetch?
  • Two editors, two disjoint fields, no overlap. Does your answer still refuse the second write, and should it?

How would you design a system to handle high-throughput transaction queuing while ensuring data consistency?

Medium · Technical & Domain Expertise

Approach

  1. Avoid the dual write: commit the transaction row and an outbox event in the same database transaction, then have a relay publish the outbox to the log (Kafka or similar). Writing to the DB and the broker separately can lose or invent events when one of them fails.
  2. Partition the queue by account or wallet id, so each account's events are processed in order inside one partition. Throughput then scales with the number of partitions. The trade-off is that a hot account caps at one consumer, and there is no ordering across accounts.
  3. Assume at-least-once delivery and make consumers idempotent: give each transaction a unique id with a unique constraint or a processed-events table, so a redelivered message is a no-op. Exactly-once effects come from idempotency, not from the broker.
  4. Keep balances correct with an append-only double-entry ledger and a guarded update (UPDATE ... SET balance = balance - :amt WHERE id = :id AND balance >= :amt, or an optimistic version check). Drive each transaction through an explicit status state machine.
  5. Handle failure explicitly: retry with exponential backoff and jitter, send poison messages to a dead-letter queue, alert on consumer lag, and run a reconciliation job that compares the ledger with the external rails (chain or bank) and flags any drift.

Follow-up

  • A consumer applies the debit and then crashes before committing its offset. What happens on restart, and why is that safe?
  • One merchant account suddenly sends most of the traffic. How do you keep its partition from becoming the bottleneck without breaking per-account ordering?
  • How would you detect and repair a ledger that has drifted from on-chain balances?

Can you explain how you would troubleshoot an API integration failure in a production environment?

Medium · Technical & Domain Expertise

Approach

  1. Scope it before touching anything: which partner or endpoint, since when, what fraction of calls, and whether it lines up with a deploy, a config change, a credential or certificate rotation, or a partner-side release.
  2. Classify the failure by layer. DNS, TLS or connection errors come before any HTTP status. 401/403 points to credentials, signatures or clock skew on signed requests. 400/422 points to a contract or schema change. 429 means rate limits. 5xx and timeouts mean the upstream or the network.
  3. Follow one failing request end to end by its correlation or request id. Read the logs and the raw (redacted) JSON request and response, headers included, and diff them against a request that succeeded. A renamed field, a changed enum value or a different decimal precision shows up here.
  4. Reproduce with the same payload against the sandbox or with curl, and check the webhook side as well: delivery attempts, signature verification failures and events that were received but rejected.
  5. Mitigate before the root cause is found: retry only requests that carry an idempotency key, open a circuit breaker or roll back, then reconcile any operation left half-applied. Close with a postmortem and the alert that would have caught it sooner.

Follow-up

  • The call to a payments partner timed out. Did the transfer happen, and how do you find out before retrying?
  • Only 2% of requests fail and the partner says nothing changed on their side. What do you look at next?
  • What logging and metrics would you add so the next incident takes minutes to diagnose rather than hours?

What are the primary security considerations when building a wallet orchestration layer?

Medium · Technical & Domain Expertise

Approach

  1. Start with key custody: no single host or person should ever hold a full private key. Compare HSM-backed keys, on-chain multisig and MPC threshold signing. Split funds into hot, warm and cold tiers and keep the hot balance to what withdrawals actually need.
  2. Put a policy engine in front of every signature: destination allowlists, per-transaction and velocity limits, and quorum approval above a threshold, with the person who creates a withdrawal kept separate from the person who approves it. The signer should sign only the exact payload that was approved, bound by its hash.
  3. Isolate the signing service: a narrow internal API, mTLS with short-lived credentials, least-privilege access, no key material in logs or environment variables, and an append-only, tamper-evident audit log of every request and approval.
  4. Validate transaction integrity: the address format and checksum, the correct network (so funds are not sent on the wrong chain), replay protection (chain id under EIP-155, per-address nonces on account-based chains) and an idempotency key, so a retried request cannot broadcast twice.
  5. Plan detection and response: anomaly alerts on withdrawal patterns, a kill switch that pauses outbound transfers, rehearsed key rotation and recovery, and continuous reconciliation of on-chain balances against the internal ledger.

Follow-up

  • When would you choose MPC over on-chain multisig, and what does each cost you (chain support, fees, on-chain visibility, operational complexity)?
  • A B2B partner's API key is stolen. Which controls limit the damage, and how fast can you contain it?
  • How do you defend against an insider who has access to both the approval tool and the infrastructure?

How do you approach gas management and fee optimization in a multi-chain environment?

Medium · Technical & Domain Expertise

Approach

  1. Hide each chain behind a fee-estimator interface, because the fee models differ. Ethereum (EIP-1559) has a burned base fee plus a priority tip, capped by maxFeePerGas. Bitcoin charges a fee rate in sat/vB, and the transaction's size depends on how many UTXOs it spends. Rollups add a charge for posting data to L1.
  2. Estimate from live data: eth_estimateGas for the gas limit with a safety margin, and eth_feeHistory percentiles for the tip. On Bitcoin, use mempool-based estimates such as estimatesmartfee. Choose a confirmation target per transaction class, so a customer withdrawal and an internal sweep get different fees.
  3. Manage nonces and stuck transactions. Allocate nonces per sending address through one serialized nonce manager, because a gap blocks every later transaction. Speed up a stuck Ethereum transaction by resending the same nonce with higher fees (geth requires at least a 10% bump). On Bitcoin, use RBF or CPFP.
  4. Cut cost structurally: batch many Bitcoin payouts into one transaction with many outputs, consolidate UTXOs when fees are low, schedule non-urgent sweeps for cheap periods, and route over the cheaper network when an asset exists on several chains.
  5. Fund gas and account for it. Hot addresses need native-token balances (an ERC-20 transfer still pays gas in ETH), so monitor and auto-top-up gas wallets. Record every fee in the ledger and decide whether the customer's quote includes it, with a quote expiry that covers fee swings.

Follow-up

  • Fees spike between the moment you quoted the customer and the broadcast. Who absorbs the difference, and how do you bound it?
  • A transaction is dropped from the mempool and later transactions on that address are stuck. Walk through recovery.
  • How would you test fee estimation and replacement logic without spending real funds?

How would you design a sandbox environment for third-party developers to test our API integrations?

Medium · Problem-Solving & Architecture

Approach

  1. Give the sandbox its own base URL and its own keys (visibly prefixed test keys) with the same API contract and versioning as production. It runs the same service code, but the chain, bank, card and KYC providers are swapped for simulators or testnets, so real funds never move.
  2. Make outcomes deterministic and triggerable: reserved amounts, test identities or headers that force a KYC rejection, insufficient funds, a pending-then-confirmed transfer or a provider timeout, plus endpoints that advance a transaction's state on demand so partners can test every branch.
  3. Deliver webhooks exactly as production does: the same signed payloads, the same retry schedule and the same event ids. Show a per-partner log of delivery attempts with a replay button, so partners can test signature checks, deduplication and out-of-order handling.
  4. Prevent drift: generate production and sandbox docs and validation from one OpenAPI spec, run contract tests against both, and deploy them from the same pipeline. Weigh testnets (realistic, but flaky and dependent on faucets) against mocks (deterministic, but they can hide chain behaviour).
  5. Treat it as multi-tenant: isolate each partner's data, apply rate limits and quotas, offer a data reset, and give partners request logs searchable by request id so they can debug without opening a ticket.

Follow-up

  • How do you stop sandbox behaviour from drifting away from production as the API evolves?
  • A partner wants to test what happens when they retry a timed-out request. What does the sandbox give them?
  • The public testnet you depend on goes down. What does that do to partners, and how would you design around it?

What is your strategy for handling edge cases in payment processing or KYC flows?

Medium · Problem-Solving & Architecture

Approach

  1. Model each payment and each verification as an explicit, persisted state machine (initiated, pending review, approved, settled, failed, reversed), with only legal transitions allowed. Every edge case then becomes a named transition instead of a scattered if-statement.
  2. Make every entry point idempotent. Store the client's idempotency key with a hash of the request; the same key with a different payload is rejected. Deduplicate provider webhooks by event id, and check the current state before applying an event, so duplicate or out-of-order deliveries are harmless.
  3. Treat a timeout as an unknown outcome, not a failure: query the provider by reference before retrying. Run reconciliation against processor and bank settlement reports. Plan for reversals that arrive days later (ACH returns, chargebacks) when the crypto already delivered cannot be pulled back, using holds or limits on new funding.
  4. Keep money exact: integer minor units or a decimal type, never floats; per-asset precision (8 decimals for BTC, 18 for ETH in wei); one explicit rounding rule; and a price quote with an expiry, so market movement during a slow step is bounded.
  5. For KYC, fail closed. If the verification provider is down, queue the case rather than approving it. Route sanctions-screening hits, name mismatches and document resubmissions to a manual-review queue, tie transaction limits to the verification tier, and keep an audit trail of every decision.

Follow-up

  • The provider's webhook arrives before your own API call has returned. How does your design handle that ordering?
  • The KYC vendor is down for several hours during a traffic peak. What do users see, and what happens to their pending transactions?
  • How would you test these edge cases: which failures would you simulate, and at which layer?

Listing latency scales with page size, not with filters

Easy · n+1 · latency · query batching

The tenant listing endpoint reads resource filtered by tenant_id and status, ordered by updated_at DESC, and returns each row plus the owner's display name from app_user and the actor of that resource's latest resource_revision. p99 is 55 ms at 10 rows per page and 1.4 s at 200. Database telemetry shows 401 statements per request, each under 1 ms, and nothing in the slow-query log. Diagnose the cause and give the fix, stating the statement count per request and the p99 you expect afterwards.

Approach

  1. Read the counters before forming a theory. 401 statements for 200 rows is one driver query plus two per row, and sub-millisecond execution with an empty slow-query log rules out a bad plan. The time is round trips, which is why it is invisible in every per-query metric and scales with rows returned rather than with filter selectivity.
  2. Name the two per-row statements from their normalised text: a single-row app_user lookup by user_id, and a resource_revision lookup by resource_id ordered by version DESC LIMIT 1. Confirm by dropping those two response fields and watching the statement count fall to one. That locates the calls in the serialisation layer, not the repository.
  3. Check that the arithmetic accounts for the whole gap. Measure one round trip to the replica in isolation; 400 trips at roughly 3 ms of network plus 0.2 ms of execution is about 1.3 s on top of a 55 ms baseline, which matches. If the multiplication had fallen short, the N+1 would only be part of the story and you would keep looking.
  4. Batch both lookups. Collect owner_user_ids and resource_ids from the driver query, then issue WHERE tenant_id = $1 AND user_id = ANY($2) for the users, and PostgreSQL's SELECT DISTINCT ON (resource_id) ... WHERE resource_id = ANY($2) ORDER BY resource_id, version DESC for the latest revision, which the UNIQUE (resource_id, version) index serves directly. On an engine without DISTINCT ON, use a lateral join or a row_number window. Three statements per request at any page size.

Follow-up

  • The page size is capped at 200 today. What breaks first if it is raised to 2,000, and is it still this bug?
  • How do you stop the next N+1 from reaching production, given that no individual query is slow and the endpoint's tests pass?

Suggested practice checklist

The plan starts with the three reported stages and your own stories, then rehearses each reported question group in turn: transaction pipelines, API integration and sandbox design, wallet security and payment edge cases.

Day 1 — Map the loop against the role's requirements

  • Write the reported sequence (Recruiter Screen, Coding Assignment, Meetings with Managers) and next to each stage, what you still need to learn about it from the recruiter.
  • List the requirements candidates describe (5+ years, API-first B2B, REST and webhooks, log and payload troubleshooting) and attach one project from your history to each.
  • Choose four or five projects that will anchor your stories for the rest of the week.

Deliverable: A one-page loop map, a requirement-to-project table and a shortlist of four or five anchor projects.

Day 2 — REST experience and the speed-versus-architecture trade-off

  • Write the REST and scalability answer for one API you owned: consumers, pagination, idempotency, errors, rate limits, versioning, webhooks, and one measured result.
  • Write the trade-off story as a situation, options, decision, guardrails, result and payback, and name what you refused to compromise.
  • Say both answers aloud once and cut anything that is a term without a decision.

Deliverable: Two written outlines (REST experience and the trade-off story) plus one recorded spoken run of each.

Day 3 — Collaboration, code review and pivot stories

  • Write the product manager or compliance collaboration story, including their constraint, your options and the agreement.
  • Write the code review answer with one concrete example where a review changed your design and the habit it left you with.
  • Write the pivot story with what you kept, what you discarded and how you communicated the new plan.

Deliverable: Three written story outlines, each ending with a result and a lesson, mapped to the five behavioral prompts.

Day 4 — Transaction pipelines and idempotent processing

  • Sketch a design for high-throughput transaction queuing with consistency: the partition key, the write path, the ordering guarantee and how duplicates are rejected.
  • Work the practice drills on keeping soft-deleted accounts from blocking re-registration and on the update path that detects a concurrent edit.

Deliverable: One queue design diagram with failure handling, plus solved practice drills for the event batch, rolling failure rate and both SQL tasks.

Day 5 — API integration failures and the partner sandbox

  • Write a triage sequence for an API integration failing in production: confirm scope, read the logs, compare the request and response payloads, check the webhook deliveries and retries, then isolate the failing hop.
  • Sketch a third-party sandbox: separate credentials, synthetic data, simulated failure and delay cases, parity with production contracts and a reset path.

Deliverable: A written triage checklist, a one-page sandbox design and a solved latency drill.

Day 6 — Wallet security, gas and payment edge cases

  • List the controls around a wallet orchestration layer: who can trigger a signature, approval and limit rules, key custody boundaries, an audit log and alerting on unusual requests.
  • Write how you would handle fees and gas across several chains: estimating fees, resubmitting a stuck transaction, and keeping users informed of the cost.
  • List ten edge cases for a payment or KYC flow, such as a duplicate callback, a verification that succeeds after the user left or a partial settlement, and a handling rule for each.

Deliverable: A security control list, a fee-management outline and a ten-row edge-case table with handling rules.

Day 7 — Full rehearsal and assignment hygiene

  • Answer aloud in sequence the trade-off story, the collaboration story and the high-throughput queue design, then replay the recording and mark vague spots.
  • Build or review a small REST service with a README, assumptions and failure-path tests, as a template for a coding assignment.
  • Write two or three questions for each meeting and the questions you will ask the recruiter about next steps.

Deliverable: Three recorded answers with a fix list, a finished assignment template with README and tests, and a written question list for interviewers.

Behavioral prep for Coinme

Candidates report that the people-side questions cover your REST and scalability experience, trade-offs under deadline pressure, working with product and compliance colleagues, taking code review feedback and reacting to changed requirements. Candidates are also told to use the STAR method and to explain the reason behind each technical decision. For this role, choose stories from API, payments or integration work, and make sure each one shows a decision you made, the alternative you gave up and what you measured afterwards.

  1. Describe a time an API integration failed in production and how you found the cause.

Describe your experience with REST APIs and designing for scalability.

Medium · Technical & Domain Expertise

Approach

  1. Choose one API you owned and open with its consumers, its traffic shape and the constraint that made it hard; a partner-facing API is the best fit for this loop because it is described as API-first B2B work.
  2. Cover concrete design decisions: resource naming and versioning, cursor pagination in place of offset on large tables, idempotency keys on any POST that creates an order or moves money, and one consistent error body with machine-readable codes.
  3. Cover scaling decisions: stateless services behind a load balancer, cache headers or ETags on reads, per-client rate limits returning 429 with a retry hint, and slow work moved to a queue so the call returns 202 plus a status resource or a webhook.
  4. Add webhook mechanics if you built them: signed payloads, retries with backoff, and a delivery id so the receiver can ignore duplicates.
  5. State what you measured before and after, such as p95 latency, error rate or requests per second, using only numbers you actually have. The mistake that sinks this answer is a list of buzzwords with no decision you personally made.

Follow-up

  • How would you version this API without breaking existing partners?
  • How do you make webhook delivery reliable when the receiver is down for hours?
  • When would you choose offset over cursor pagination, and what do you lose with cursors?

Tell me about a time you had to make a trade-off between speed-to-market and architectural perfection.

Medium · Problem-Solving & Architecture

Approach

  1. Pick a story with a real deadline and a real business reason, and state both options plainly: the fast path with its shortcut and the cleaner build, with the cost of each.
  2. Explain what you chose and why, then name the guardrails that made it safe: a feature flag, tests around the path that moves money, an API shape you refused to change because partners would depend on it, and a tracked ticket with an owner for the shortcut.
  3. Name what you would not compromise, such as ledger consistency, security controls or compliance checks. A strong answer cuts corners in internal layers and keeps the audit trail and the correctness of balances intact.
  4. Close with the result and the payback: when the debt was repaid, what triggered it, and what the shortcut actually cost. The mistake is claiming there was no trade-off, or telling a story where the shortcut caused an incident and nothing was learned.

Follow-up

  • How did you decide which corners were safe to cut and which were not?
  • When did you pay the debt back, and what forced the timing?
  • Looking back, would you make the same call today?

Describe a challenging collaboration with a product manager or a compliance lead.

Medium · Behavioral & Team Collaboration

Approach

  1. Choose a conflict with a real stake, such as a compliance requirement that added steps to a user flow, or a product deadline that clashed with a risky design. Say in two sentences what each side wanted.
  2. Show that you first learned the other person's constraint: the rule behind the compliance request, or the commitment behind the deadline. Then bring options with costs, for example a staged flow, a narrower first release or an extra check on higher-risk cases, in terms that person can weigh.
  3. Describe the artifact that resolved it, such as a requirements document that listed error states, edge cases and compliance conditions, or a short decision record both sides signed off on.
  4. Give the outcome and what you changed in how you work with that function. The mistake is casting the other person as an obstacle; a good story ends with a working relationship.

Follow-up

  • What did you do when they would not move on their position?
  • How did you explain a technical constraint to someone non-technical?
  • What would you do differently at the start of that project?

How do you handle feedback during a code review?

Medium · Behavioral & Team Collaboration

Approach

  1. Answer both sides. As an author: read each comment as being about the code, ask a clarifying question when the intent is unclear, separate blocking comments from nits, and reply with a change or a reasoned response backed by evidence such as a test or a measurement.
  2. Give one specific example where review changed your code for the better, such as a missed race condition, a missing idempotency check or an unclear error path, and say what you did so it would not recur: a test, a checklist item or a lint rule.
  3. Show the habits that make feedback cheap: small pull requests, a description that states the intent and the risks, and self-review before requesting others.
  4. Cover disagreement: if you still disagree after one round, move to a call or a short write-up and defer to the agreed standard. The mistake is saying you never get pushback, or describing feedback as something you tolerate.

Follow-up

  • What do you do when you disagree with a more senior reviewer?
  • Tell me about review feedback you gave that landed badly, and what you changed.
  • How do you handle a review with dozens of comments?

Tell me about a time you had to pivot quickly due to changing business requirements.

Medium · Behavioral & Team Collaboration

Approach

  1. Choose a pivot where the requirement changed after work had started, such as a partner change, a regulatory change or a new product decision. State what changed, what had already been built and the new date in two sentences.
  2. Show your sequence: list what is reusable and what is thrown away, estimate the new cost, and take options to the product manager (cut scope, move the date, or both) before you start rebuilding.
  3. Describe how you delivered: thin slices behind a flag, the tests you kept on the money-moving or compliance-sensitive path, and updated documentation so others were not working from the old plan.
  4. Finish with the result and one design change that makes the next pivot cheaper, such as isolating the volatile rule behind an interface. The mistake is a story about unplanned overtime with no renegotiated scope, or one that blames product for changing its mind.

Follow-up

  • How did you decide what to throw away and what to keep?
  • How did you communicate the new timeline and its risks?
  • What would you design differently now to make a pivot like that cheaper?