# StackMonkey design files, for AI agents StackMonkey (https://stackmonkey.dev) is a browser simulator for learning how distributed systems behave. You draw boxes (clients, load balancers, services, caches, queues, databases), press Run, and watch queues fill, requests time out and servers fall over. It is a learning model, not a prediction of production. Only Rust, Go, Java, Node and Python costs are measured; everything else is an estimate and is labelled as one. ## What to do 1. Write a design file in the format below. 2. Save it as `something.json`. 3. In the simulator open the Export menu, choose "Import a diagram file", and pick it. Nothing is uploaded; the file is read in the browser. 4. Press Run. Read the "Estimated limit" card and the failure messages before trusting any number. There is no hosted API. The file is the interface. ## Format ```json { "version": 1, "architecture": { "nodes": [ { "id": "users", "type": "client", "name": "Browsers", "rate": 500 }, { "id": "lb", "type": "loadBalancer", "name": "Load balancer", "algorithm": "leastConnections", "workers": 5000 }, { "id": "app", "type": "service", "name": "App servers", "runtime": "go", "cores": 2, "workers": 200, "serviceMs": 2, "queueCapacity": 200, "instances": 2 }, { "id": "cache", "type": "cache", "name": "Redis", "engine": "redis", "serviceMs": 0, "hitRatio": 0.9, "workers": 1000, "queueCapacity": 500 }, { "id": "db", "type": "database", "name": "PostgreSQL", "engine": "postgres", "serviceMs": 0, "cores": 2, "workers": 64, "queueCapacity": 200 } ], "edges": [ { "from": "users", "to": "lb" }, { "from": "lb", "to": "app" }, { "from": "app", "to": "cache", "fallback": true }, { "from": "cache", "to": "db" } ] } } ``` A bare `{ "nodes": [...], "edges": [...] }` is also accepted. ## Rules - Every node needs a unique, non empty string `id` and a `type`. - `type` is one of: `client`, `apiGateway`, `loadBalancer`, `service`, `queue`, `cache`, `database`. - Every edge needs `from` and `to`, and both must be node ids. An edge means "calls". Requests start at a client and flow along edges. - Calls must not go in a circle. - At most 100 nodes and 300 edges. Numbers beyond the limits are cut back, not rejected. Totals are capped at 100,000 users and 2,000 database machines. - Unknown fields are ignored. A node without coordinates is laid out automatically. - If the import fails you get a one line reason, for example `Node "x" has an unknown type`. Fix that and import again. ## Fields worth setting All fields are optional. Times are milliseconds. - client: `rate` (requests per second), `clientMode` (`open`, `concurrent`, `websocket`, `upload`), `users`, `thinkMs`. - service: `runtime` (`rust`, `go`, `java`, `node`, `python`), `cores`, `workers` (calls at once), `serviceMs` (own work per call at Go speed), `queueCapacity`, `instances`. - loadBalancer: `algorithm` (`roundRobin`, `random`, `leastConnections`, `powerOfTwo`, and weighted variants). - cache: `engine` (`redis`), `hitRatio` (0 to 1), `workers`, `queueCapacity`. - database: `engine` (`postgres`), `cores`, `workers`, `queueCapacity`, `replicas`, `shards`. - apiGateway: `rateLimit`, `rateBurst`, `workers`. - edge: `probability` (0 to 1), `timeoutMs`, `maxRetries`, `retryDelayMs`, `breakerFailures`, `fallback` (on a cache edge: carry on to what is behind it when the cache fails). Start from the example above and change one thing at a time. Say which numbers you assumed, because the model is only as good as the inputs.