Why crypto exchange API development fails at peaks
A peak in activity breaks not the front end, but the trading core: the flow of orders and cancellations grows severalfold, the order book is rebuilt on every update, and the load on the trading core stops being even.
The processing queue lengthens, the response time for order confirmation grows — and the first to feel it are those who trade through programmatic access rather than through a web form.
The second failure scenario is connection drops. During a spike, channels break en masse, clients go into reconnection, and each one again requests a snapshot of the order book and subscriptions.
If crypto exchange API development does not separate the snapshot and the stream of changes by sequence, the client assembles the order book from heterogeneous parts: some levels are outdated, some arrived twice, and the trading bot makes a decision based on an unreliable picture and worsens the load with retries.
The most expensive is the desynchronization of balances and the transaction log. When a debit, credit, and log entry are not bound by a single transaction, or a repeated request creates a second operation, the balance in the interface diverges from the actual one.
Then manual incident investigations begin: reconciliation against exports, withdrawal blocking, loss of user trust — even though formally each individual handler completed without error.
The fourth point is degradation, not failure. The core is alive but responds more and more slowly, and it is unclear where the limit is: there is no separation of streams into order book reads and trade execution, no rate limits on requests, no priority queue for cancellations.
We examine exactly where resilience is lost at peaks and how it is closed at the level of the contract, limits, and error handling.
What a dedicated API layer provides for trading logic
A dedicated API layer is not a 'layer for beauty's sake,' but a circuit that accepts orders, validates them, and queues them in front of the trading core.
Transport, formats, and limits live here, while the core processes only a normalized stream and does not know where it came from. This isolation of trading logic provides the main thing: a spike at the input does not turn into an increase in matching response time.
During spikes, the layer works as a buffer with an explicit policy: rate limiting by access key, priority of cancellations over new orders, idempotency by client identifier so that a repeated request does not open a second position.
Tail latencies remain within a specified corridor rather than growing linearly with load. The metric here is response time at high percentiles under peak and the share of orders rejected with an explicit reason.
Recovery time is determined by the fact that the layer keeps a log of accepted orders before passing them to the core. When the core restarts or fails, unconfirmed orders are replayed from the log, and the client receives a final status rather than a 'hanging' operation.
In practice, this moves recovery from manual investigation to automatic retry: the share of lost orders goes to zero within the log retention window.
The most expensive class of failures disappears — 'order accepted but neither executed nor canceled,' when the position is restored from statements. What remains are explicit errors with a code and response that the client handles on its own, without contacting support.
At the same time, the layer decouples releases: changes in trading logic do not touch the access contract, and extending formats does not require stopping the core.
On-demand requests or a stream: comparing modes
The trading core delivers data in two ways, and the choice between them determines both response latency and infrastructure load. One-off on-demand requests return a slice of state at the time of the call: balance, order list, trade history for a period.
A persistent stream keeps a connection open and pushes changes as they appear — order book, quotes, order statuses.
The access mode is selected for the load profile: how many clients are online simultaneously, how often data changes, and whether lagging behind the market is critical. Below are three options and their limitations.
| Access mode | When it fits | What limits it |
|---|---|---|
| One-off on-demand requests | Reference data, trade history and reports, operator actions, occasional balance checks | Latency on every call, rate limits on requests, price changes between calls are not visible; frequent polling needlessly loads the core |
| Persistent update stream | Quotes, order book, trade feed, trading widgets — everything where the market needs to be seen without delay | Holds a connection per client, requires reconnection and catch-up of missed data, sensitive to drops in mobile networks |
| Hybrid scheme | Production exchange application: stream for market data, one-off requests for history and private operations | More complex to develop and maintain: two sets of access rights, state synchronization after a drop, separate load control |
The hybrid scheme is most common in production: it reduces traffic volume and simplifies recovery after a connection drop.
How implementation proceeds: stages of engineering work
We work in a sequence where each stage ends with a verifiable artifact, not an interim report. The order is fundamental: changes in the trading circuit go from read to write, so first we record how the system lives now, and only then do we touch what orders pass through.
-
Circuit audit. We analyze services, queues, storage, and current limitations on the side of liquidity providers. We find where events are lost, on which requests latency grows, and which methods clients already use. The result is a map of bottlenecks with priorities.
-
Interaction scheme. We design contracts: REST methods for requests and WebSocket subscriptions for price, order book, and trade streams. We fix response formats, error codes, rate limits, and behavior on connection drop so that the client and your team read one document.
-
Rollback plan. We add new methods alongside the old ones, keep switch points controllable, and the interface version lives in parallel until clients migrate. Rollback is returning traffic to the old circuit without losing orders.
-
Load testing. We run a profile close to production: order peaks, mass subscriptions, reconnections. We look not only at throughput but also at behavior under partial failures — what the client sees when one node goes down.
-
Observability. Metrics for each method, request logs, alerts for deviations from the norm. Before operation, it must be visible which client and which call cause a degradation.
-
Handover of regulations. We hand over contract documentation, schemes, rate policies, and incident procedures, and conduct a review with your engineers. After that, you run support yourselves or leave it to us.
What we hand over to the customer: configurations and regulations
We hand over not a folder with a description, but a working set: configurations sit in the repository next to the code, deploy on a clean environment without us, and schemes and policies are versioned together with changes. Below is exactly what goes to the customer based on the project results.
- Service configurations — connection parameters for quote streams, request rate limits, load profiles, environment variables, and key rotation procedure.
- Data flow schemes — the path from the price source to trade recording: where the cache sits, where the event queue is, which WebSocket channels and REST method groups bypass it.
- Access policies and limits — role matrix, separate keys for reading and for trading operations, amount and rate limits, blocking rules for anomalies.
- Operations regulations — maintenance windows, change rollout procedure, monitoring with alert thresholds, and on-call actions for typical deviations.
- Recovery scenarios — rollback points, procedure for restoring from backups, re-synchronization of the order book and balances, integrity check after recovery.
- Test results — the load profile under which testing was performed, a report on latencies and failures, a list of known limitations with risk assessment.
The set lives together with the code: when a scheme or policy changes, the document is edited in the same change, otherwise it becomes outdated within a week and the on-call shift again goes into correspondence.
Case study: exchange grew fivefold without rewriting the core
The exchange came to us at a stage when the trading core could handle the load, but the API layer no longer could.
With three thousand simultaneous WebSocket connections, the market data publication queue grew faster than it was drained, orders dropped by timeout, and the on-call shift spent half its time manually investigating incidents.
What the metrics showed before
- 3,000 simultaneous connections — the ceiling after which failures began.
- 92% of orders reached the core on the first send; the rest were retries and manual reconciliation.
- Recovery after a node failure — about 40 minutes of on-call work.
- 60–70 manual investigations per week, mainly subscription drops during market spikes.
What we changed and what the result was
The API layer was split into independently scalable services: order intake, private user subscriptions, and public market data broadcasting.
Subscription state was moved to a distributed cache on Redis, we added retry with duplicate protection, request rate limiting at the ingress, and automatic removal of a node from load balancing when a liveness check fails.
As a result, the number of simultaneous connections grew to 15,000, the share of successful orders — to 99.7%, and node recovery takes less than two minutes without on-call involvement.
Manual investigations dropped to 1–2 per week and concern disputed market situations rather than infrastructure failures. We did not change the trading core — the fivefold growth happened on the previous logic.
What to do if the trading core is already running?
A running core is an asset that cannot be stopped for repairs. Therefore we build the access layer alongside, not inside: the core continues to calculate orders, positions, and risks, and only the way this data goes outward changes.
This approach removes the main risk of the project — the need to rewrite what already generates turnover.
On the outside, an access gateway appears: it holds contracts for client applications and translates them into the core's internal interfaces through adapters.
The core is not rewritten — the adapter reads the same tables and queues as before and converts them into synchronous requests and streaming event subscriptions.
We fix the contract in OpenAPI, so that client teams, mobile applications, and external integrators work with one document rather than oral agreements.
Phased connection gives manageable risk: first the gateway serves only market data, then trade history and balances, and only then operations that affect account state.
Each stage runs under comparison — identical requests go to the old and new paths, response discrepancies are logged and investigated before switching. The share of traffic on the new path grows in steps, not in a single switch.
We keep interface compatibility at the contract level: we do not remove previous field versions while call metrics show live clients, and we announce deprecation based on actual usage, not the calendar.
Reverse rollback is a mandatory acceptance condition: routing returns to the previous path in one operation, without migrations and without state loss. The source of truth remains in the core, so the old and new paths do not diverge in data.
This way the exchange continues trading without stopping, and the access layer is expanded in parts and can be rolled back at any time. Describe your task — we will come back with an estimate and a stage-by-stage plan.
Technical doubts worth resolving before the start
Customers' doubts sound the same, and the answers to them determine whether the exchange will withstand the load or fall apart at the first spike in activity.
We address key engineering questions before work starts — so that architectural decisions are discussed at the planning stage, not at the moment of failure.
How is data integrity guaranteed during writes?
Each operation runs in a transaction together with a log entry: balances, orders, and trades change in a single atomic operation and cannot diverge during a drop. A repeated request send is cut off by an idempotent key — a duplicate does not turn into a second trade.
How is the system updated without breaking client connections?
Services are updated one at a time: the new version is brought up alongside, takes traffic, and only then is the old one taken out.
Active subscriptions migrate to it via a smooth handover, without losing updates and without a spike in reconnections, and the previous interface remains compatible during the transition.
How are access rights separated?
Access is built on roles and keys with separate permissions: reading, trading, and withdrawal are different rights, supplemented by volume limits and an address list.
A key with trading permission does not allow withdrawing the balance, and key rotation and access revocation happen without stopping the service.
What happens when there is a discrepancy with an external system?
Discrepancies are caught by regular reconciliation, and each case goes into an investigation queue with full context: the transaction log, responses from external systems, the order state at the time of failure.
The log is kept in an immutable form, so restoring a client's position relies on the primary source, not a guess.
Let's discuss the task: what is needed to start work
To estimate crypto exchange API development, rather than answering with a range like 'about that much,' a minimum set of input data is needed. The more specific the input, the more accurate the stage timelines and the fewer reworks at the junction with the trading core.
- Which scenarios the interface serves: trading operations, real-time quote and trade stream, history, fund withdrawal, service calls.
- What already exists on the core side: how it provides state now, which data is available directly, and which will have to be assembled.
- Access model: how keys are issued, whether role-based rights and request rate limits are needed.
- Load and reliability requirements: peak request rate, acceptable response latency, behavior on connection drop.
- Infrastructure: where services are hosted, whether logging and monitoring exist, how updates are released.
- Your deadlines and milestones by which the interface must be ready — we build the sequence of stages around them.
The discussion order is simple: a short analysis of the task, then clarifying questions based on the list above, and separately we go through which calls are synchronous and which are an event stream.
After that we send a written work plan: design of schemes and access rules, implementation, checks on the test environment, load runs, documentation, and commissioning.
Design usually takes one to two weeks, implementation — from three, and checks and documentation proceed in parallel with it. The estimate and plan remain with you regardless of the decision to start.







