Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

29 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ—οΈ System Design Playground

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.


The Problem

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.


What It Does

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.


Architecture

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

Tech Decisions

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.


Setup

1. Clone the repository

git clone https://github.com/IELSK/system-design-playground.git
cd system-design-playground

2. Start PostgreSQL

docker compose up -d

3. Configure environment

Create 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"

4. Backend

cd backend
npm install
npx prisma generate
npx prisma migrate dev
npm run dev          # http://localhost:3333

5. Frontend

cd frontend
npm install
npm run dev          # http://localhost:5173

Running Tests

cd backend
npm test             # 32 tests (needs PostgreSQL running)

API Endpoints

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

Example Workflow

  1. Build β€” Drag a Client, Load Balancer, API Server, Cache, and Database onto the canvas. Connect them.
  2. Configure β€” Click each node to set parameters (instances, RPS limits, hit rates, etc.).
  3. Branch β€” Add a Queue β†’ Worker path alongside the Cache path. Click edges to set traffic split (e.g. 70% reads / 30% writes).
  4. Simulate β€” Click "Simulate" to see bottlenecks, latency breakdown, and utilization per node.
  5. Break things β€” Open the Failures panel, set a node to "node_down" or "capacity_degraded", re-simulate.
  6. Scale β€” Click "Scale" to explore how the system behaves from 100 to 20,000 rps.
  7. Save & Share β€” Cloud save your architecture, toggle it public, and share the link.

Screenshots

Mounted Canva image

Performance Dashboard image

Failure Applied image

Scale Analysis image

My Architectures image


Demo

Demo

Demo


License

MIT

About

A visual tool for modeling and simulating distributed system architectures using queuing theory (M/M/c), bottleneck detection, and scale projection.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages