A simplified, highly available stock exchange REST API.
- API: Node.js + TypeScript (Express)
- State: Redis - shared across all instances
- Load balancer: Nginx -
least_conn+ automatic failover - Orchestration: Docker Compose - 3 independent API replicas
Atomic buy/sell operations are implemented as a Redis Lua script to prevent race conditions under concurrent load.
Docker must be installed and running. No other runtime is required.
Linux / macOS
chmod +x start.sh
./start.sh 3000Windows
start.cmd 3000The API is available at http://localhost:3000.
To stop: docker-compose down
Three API instances run behind Nginx. When /chaos kills one instance:
- Nginx detects the failure via
proxy_next_upstreamand retries on a healthy instance - Docker restarts the killed container automatically (
restart: unless-stopped) - All state lives in Redis, so any instance can serve any request Killing one instance does not interrupt the service.
Returns current bank inventory.
{ "stocks": [{ "name": "Apple", "quantity": 100 }] }Replaces the entire bank state.
{ "stocks": [{ "name": "Apple", "quantity": 100 }, { "name": "Google", "quantity": 50 }] }Returns 200 Bank state updated.
Buy or sell one unit of a stock. Creates the wallet if it does not exist.
Body:
{ "type": "buy" }| Status | Reason |
| 200 | Success |
| 400 | No stock in bank (buy) / no stock in wallet (sell) |
| 404 | Stock does not exist in the bank |
Returns full wallet state.
{ "id": "alice", "stocks": [{ "name": "Apple", "quantity": 3 }] }Returns a single quantity number.
3
Returns all successful trade operations in order of occurrence. Bank resets are not logged.
{
"log": [
{ "type": "buy", "wallet_id": "alice", "stock_name": "Apple" },
{ "type": "sell", "wallet_id": "bob", "stock_name": "Apple" }
]
}Kills the instance that served the request. The remaining two instances continue handling traffic.