A production-credible, low-latency perpetual DEX matching engine built with Node.js + TypeScript, designed to demonstrate deterministic execution, exchange-grade architecture, and real-time systems design.
- API Base: https://perp-dex-matching-engine-production.up.railway.app/
- WebSocket: wss://perp-dex-matching-engine-production.up.railway.app/ws
Example: curl -X GET https://perp-dex-matching-engine-production.up.railway.app/orderbook
This project implements a simplified but correct and extensible matching engine inspired by real-world exchange infrastructure.
The system prioritizes:
- deterministic order execution
- strict price-time priority
- low-latency processing
- real-time event streaming
- observable system performance
- Price-time priority (FIFO within price level)
- Partial fills with correct residual handling
- Maker price execution (resting order price)
- Deterministic execution flow
-
Price-level architecture:
Map<price, FIFO queue>
-
Guarantees:
- O(1) best bid/ask access
- strict FIFO ordering within price levels
-
Efficient removal of filled orders
CREATE → MATCH → PARTIAL FILL → REST → CANCEL
- Supports full lifecycle including cancellation
- Idempotent order submission
POST /order→ place orderDELETE /order/:id→ cancel orderGET /orderbook→ full snapshotGET /trades→ executed tradesGET /metrics→ system performance
-
WebSocket endpoint:
/ws -
Streams:
- trades
- orderbook updates
Event-driven architecture using an internal event bus.
-
Deterministic matching (single-threaded execution)
-
Strict price-time priority
-
Monotonic sequence numbers for:
- ordered event delivery
- deterministic replay
- client-side consistency
- Token bucket per IP
- Burst-friendly design
- Prevents API abuse without affecting trading bursts
Client (REST / WS)
│
▼
Fastify API
│
▼
Matching Engine
│
▼
Order Book
│
▼
Event Bus ───▶ WebSocket Stream
- Match against lowest ask
- Condition:
ask.price <= buy.price
- Match against highest bid
- Condition:
bid.price >= sell.price
- Executed at resting order price (maker price)
Each trade and orderbook update includes a monotonic sequenceId:
- Ensures strict ordering of events
- Enables deterministic replay
- Allows clients to detect missed updates
The engine includes built-in latency instrumentation using high-resolution timers (process.hrtime.bigint()).
totalOrders— total processed ordersavgLatencyMs— average latency per orderlastLatencyMs— most recent latencytradesCount— total executed trades
curl http://localhost:3000/metrics{
"totalOrders": 1000,
"avgLatencyMs": 0.08,
"lastLatencyMs": 0.09,
"tradesCount": 500
}- Latency measured per order processing cycle
- In-memory processing enables sub-millisecond latency locally
- Does not include network or distributed system overhead
- Node.js
- TypeScript
- Fastify
- WebSockets (
@fastify/websocket)
npm install
npm run devServer runs at:
http://localhost:3000
curl -X POST http://localhost:3000/order \
-H "Content-Type: application/json" \
-d '{"id":"1","side":"buy","price":100,"quantity":5}'curl -X DELETE http://localhost:3000/order/1curl http://localhost:3000/orderbookcurl http://localhost:3000/tradesconst ws = new WebSocket("ws://localhost:3000/ws");
ws.onmessage = (msg) => {
console.log(JSON.parse(msg.data));
};- In-memory state (no persistence)
- Single-threaded execution model
- Full snapshot streaming (no diff compression)
- Distributed matching engine
- Persistent event sourcing (Kafka / logs)
- Snapshot + incremental (delta) updates
- Horizontal scaling
- Fault tolerance and replication
- Market orders
- Order amendments
- Persistent order log
- Latency percentiles (p95 / p99)
- Prometheus / OpenTelemetry integration
- Multi-asset support
This project demonstrates:
- backend systems design
- low-latency architecture
- deterministic state machines
- real-time event streaming
- observability and performance measurement
Samar Abbas Backend Systems Engineer | Distributed Systems | Web3