A visual tool for modeling and simulating distributed system architectures. Drag-and-drop infrastructure components, connect them, configure parameters, and run simulations powered by M/M/c queuing theory to identify bottlenecks, project scaling behavior, and estimate costs.
Understanding how a distributed system behaves under load β where it bottlenecks, how latency compounds, when to scale β usually requires either expensive load testing on real infrastructure or years of intuition. This tool replaces that with interactive, visual simulation grounded in queuing theory math, letting you answer "what happens at 10k rps?" before writing a single line of infrastructure code.
The platform answers four core questions:
Where does my system bottleneck? The simulation engine traverses the architecture graph in topological order, computing per-node utilization via M/M/c queuing theory. The first node to saturate (Ο β₯ 1) is highlighted on the canvas with a red pulse.
How does my system scale? The same simulation runs at 7 traffic levels (100 β 20,000 rps), producing latency, throughput, error rate, and bottleneck curves. An interactive slider lets you explore each level, and auto-generated recommendations tell you what to scale and when.
What happens when things break? Four failure modes (node down, slow response, partial failure, capacity degraded) can be applied per node. The engine recomputes with multiplicative error composition, showing how failures cascade through the pipeline.
How much does it cost? An approximate AWS pricing model (EC2, RDS, ElastiCache, SQS, ALB) estimates monthly cost by node, and the scale analysis shows cost per 1M successful requests at each traffic level.
system-design-playground/
βββ backend/
β βββ src/
β β βββ app.ts # Express app setup
β β βββ index.ts # Entry point
β β βββ lib/ # AppError, cookies, prisma singleton
β β βββ middlewares/
β β β βββ authGuard.ts # JWT validation
β β βββ routes/
β β β βββ architecture.ts # CRUD + public sharing
β β β βββ auth.ts # Register/login/refresh/logout
β β β βββ cost.ts # POST /cost-estimate
β β β βββ health.ts # GET /health
β β β βββ simulate.ts # POST /simulate
β β βββ services/
β β β βββ architecture.ts # CRUD with ownership checks
β β β βββ auth.ts # JWT + bcrypt logic
β β β βββ cost.ts # AWS pricing model
β β β βββ simulation/
β β β βββ index.ts # Engine: M/M/c, branching, failures
β β β βββ graph.ts # Adjacency list + topological sort
β β β βββ types.ts # All simulation types
β β β βββ nodes/ # Per-type capacity calculators
β β βββ tests/ # 32 tests (Jest + Supertest)
β βββ prisma/
β βββ schema.prisma # User, RefreshToken, Architecture
βββ frontend/
β βββ src/
β β βββ components/
β β β βββ nodes/ # Custom React Flow node
β β β βββ editor/ # Sidebar, ConfigPanel, EdgePanel,
β β β β # FailurePanel, SaveDialog, Toolbar
β β β βββ dashboard/ # SummaryCards, LatencyChart,
β β β β # UtilizationBars, NodeDetailTable,
β β β β # CostBreakdown
β β β βββ scale/ # ScaleAnalysis (full-screen modal)
β β βββ pages/
β β β βββ EditorPage.tsx # Main canvas + all panels
β β β βββ MyArchitecturesPage.tsx
β β β βββ SharedArchitecturePage.tsx
β β βββ hooks/ # useAuth, useConnectionValidator,
β β β # useGraphStorage
β β βββ services/
β β βββ api.ts # Axios + interceptors
β βββ vite.config.ts # Proxy /api β localhost:3333
βββ docker-compose.yml # PostgreSQL 16
βββ CLAUDE.md # Full project context
M/M/c over static capacity math β queuing theory captures non-linear latency behavior near saturation. A node at 90% utilization has dramatically higher queue wait than one at 50%, and M/M/c models this accurately.
Topological sort with per-node demand maps β the engine computes inbound demand and output flow per node in topological order, supporting DAG architectures (branching traffic) instead of only linear pipelines.
Edge weight normalization β traffic split between branches uses relative weights, not absolute percentages. Users can input any scale (50/50, 7/3, 700/300) and the engine normalizes them to ratios among siblings.
Multiplicative error composition β when a bottleneck caps throughput and a partial_failure drops requests, survival rates multiply: surviveRatio = bottleneckRatio Γ partialSurvive. This correctly models independent failure sources.
JWT in memory + refresh in httpOnly cookie β access token never touches localStorage (prevents XSS theft). Refresh token is httpOnly (invisible to JS). Rotation on each refresh limits damage from leaked tokens.
React Flow with a single node type β all 7 component types (Client, LB, API, Queue, Worker, DB, Cache) share one ArchitectureNode component, switching rendering by data.nodeType. This keeps the node type registry simple.
Cost per 1M requests as scale metric β infrastructure cost is fixed regardless of traffic, so raw cost doesn't change. Plotting cost / throughput Γ 1M reveals efficiency: it drops as throughput grows, then spikes when the system saturates and throughput plateaus.
git clone https://github.com/IELSK/system-design-playground.git
cd system-design-playgrounddocker compose up -dCreate backend/.env:
DATABASE_URL="postgresql://sdp:sdp@localhost:5432/sdp"
JWT_SECRET="your-secret-here"
JWT_REFRESH_SECRET="another-secret-here"
PORT=3333
CORS_ORIGIN="http://localhost:5173"cd backend
npm install
npx prisma generate
npx prisma migrate dev
npm run dev # http://localhost:3333cd frontend
npm install
npm run dev # http://localhost:5173cd backend
npm test # 32 tests (needs PostgreSQL running)| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /simulate |
No | Run simulation on an architecture graph |
| POST | /cost-estimate |
No | Estimate monthly AWS cost |
| POST | /architectures |
Yes | Save architecture to cloud |
| GET | /architectures |
Yes | List user's saved architectures |
| GET | /architectures/:id |
Yes | Get a specific architecture |
| PATCH | /architectures/:id |
Yes | Update architecture |
| DELETE | /architectures/:id |
Yes | Delete architecture |
| GET | /architectures/public/:id |
No | View a shared architecture |
| POST | /auth/register |
No | Create account |
| POST | /auth/login |
No | Login |
| POST | /auth/refresh |
No | Rotate refresh token |
| POST | /auth/logout |
No | Logout |
| GET | /auth/me |
Yes | Current user info |
- Build β Drag a Client, Load Balancer, API Server, Cache, and Database onto the canvas. Connect them.
- Configure β Click each node to set parameters (instances, RPS limits, hit rates, etc.).
- Branch β Add a Queue β Worker path alongside the Cache path. Click edges to set traffic split (e.g. 70% reads / 30% writes).
- Simulate β Click "Simulate" to see bottlenecks, latency breakdown, and utilization per node.
- Break things β Open the Failures panel, set a node to "node_down" or "capacity_degraded", re-simulate.
- Scale β Click "Scale" to explore how the system behaves from 100 to 20,000 rps.
- Save & Share β Cloud save your architecture, toggle it public, and share the link.
MIT





