A real-time options trading platform like Exness built with Node.js, Express, PostgreSQL, and Next.js frontend.
This project uses Turborepo for monorepo management and includes:
- API Service (
apps/api-service/) - Express API server for authentication, trading, and balance management (Port 3001) - Engine Service (
apps/engine-service/) - Trading engine for order processing and price monitoring (Port 3002) - Price Poller Service (
apps/price-poller-service/) - WebSocket connection to Backpack Exchange for real-time prices (Port 3003) - Web (
apps/web/) - Next.js frontend application - Shared Packages (
packages/) - Shared utilities, UI components, types, and configurations
- HTTP API server for user authentication (JWT), order management, balance operations, and candle data
- Communicates with the Trading Engine via Redis streams
- Built with Express.js and TypeScript
- Runs on Port 3001
- Core trading engine that processes orders, manages positions, handles liquidations
- Monitors open positions for take-profit and stop-loss triggers
- Manages user balances in real-time and saves order data to the database
- Built with Node.js and Redis streams
- Runs on Port 3002
- Maintains WebSocket connection to Backpack Exchange for real-time BTC_USDC prices
- Sends price updates to the trading engine via Redis streams
- Built with Node.js and WebSocket
- Runs on Port 3003
The system uses PostgreSQL with Prisma ORM.
id
email
password
name
symbol
balance
decimals
userId
id
userId
side
qty
openingPrice
closingPrice
status
leverage
takeProfit
stopLoss
pnl
closeReason
- Node.js
- Docker
- PostgreSQL database (using docker)
- Redis server (using docker)
- pnpm package manager
-
Install dependencies:
pnpm install
-
Set up environment variables: Create a
.envfile in the backend directory:DATABASE_URL="postgresql://username:password@localhost:5432/trading_db" REDIS_URL="redis://localhost:6379" PORT=3001
-
Start Docker:
docker compose up -d
-
Set up the database:
npx prisma migrate dev npx prisma generate
Start all services:
pnpm run devStart specific services:
pnpm run build
pnpm run lint
pnpm run check-typesThe backend consists of three separate microservices that need to be running:
-
Start the API Service (Port 3001):
pnpm run dev:api
-
Start the Engine Service (Port 3002):
pnpm run dev:engine
-
Start the Price Poller Service (Port 3003):
pnpm run dev:price-poller
Note: All three services must be running for the platform to work properly.
For production builds:
-
Build and start API Service:
pnpm run start:api
-
Build and start Engine Service:
pnpm run start:engine
-
Build and start Price Poller Service:
pnpm run start:price-poller
POST /auth/registerPOST /auth/loginPOST /auth/logoutGET /auth/me
POST /trade/createPOST /trade/close/:orderIdGET /trade/ordersGET /trade/orders/:orderId
GET /balance
GET /candles
The services communicate via Redis streams:
engine-stream: Price updates and order requests flow from API Service and Price Poller to Engine Servicecallback-queue: Order confirmations and status updates flow from Engine Service back to API Service
Service Ports:
- API Service: 3001
- Engine Service: 3002 (internal processing, no HTTP endpoints)
- Price Poller Service: 3003 (internal processing, no HTTP endpoints)
This project uses Turborepo for efficient monorepo development:
pnpm run dev- Start all applications in development modepnpm run build- Build all packages and applicationspnpm run lint- Lint all packagespnpm run check-types- Type check all packagespnpm run format- Format code with Prettier