{"type":"excalidraw","version":2,"source":"https://AwesomeSystemDesign.dev","elements":[{"angle":0,"strokeColor":"#6577aa","backgroundColor":"#eef1fc","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-1"],"frameId":null,"roundness":null,"boundElements":[{"type":"text","id":"shape-1"}],"updated":0,"link":null,"locked":false,"id":"shape-0","type":"rectangle","seed":41,"x":36,"y":32.00000000000001,"width":390,"height":82.80000000000001,"customData":{"revealStep":1}},{"angle":0,"strokeColor":"#394557","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-1"],"frameId":null,"roundness":null,"boundElements":null,"updated":0,"link":null,"locked":false,"id":"shape-1","type":"text","seed":114,"x":56,"y":50.000000000000014,"width":350,"height":46.800000000000004,"fontSize":18,"fontFamily":1,"text":"Plan | API calls/min | Burst |\nConcurrent requests","originalText":"Plan | API calls/min | Burst |\nConcurrent requests","textAlign":"center","verticalAlign":"middle","containerId":"shape-0","lineHeight":1.3,"autoResize":false,"customData":{"revealStep":1}},{"angle":0,"strokeColor":"#628572","backgroundColor":"#edf5ee","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-2"],"frameId":null,"roundness":null,"boundElements":[{"type":"text","id":"shape-3"}],"updated":0,"link":null,"locked":false,"id":"shape-2","type":"rectangle","seed":187,"x":466,"y":32,"width":348.21832,"height":106.2,"customData":{"revealStep":2}},{"angle":0,"strokeColor":"#394557","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-2"],"frameId":null,"roundness":null,"boundElements":null,"updated":0,"link":null,"locked":false,"id":"shape-3","type":"text","seed":260,"x":486,"y":50,"width":308.21832,"height":70.2,"fontSize":18,"fontFamily":1,"text":"Free | 60 | 10 | 5\nPro | 6,000 | 100 | 50\nEnterprise| 60,000 | 1,000 | 500","originalText":"Free | 60 | 10 | 5\nPro | 6,000 | 100 | 50\nEnterprise| 60,000 | 1,000 | 500","textAlign":"center","verticalAlign":"middle","containerId":"shape-2","lineHeight":1.3,"autoResize":false,"customData":{"revealStep":2}},{"angle":0,"strokeColor":"#a68a53","backgroundColor":"#fff7e6","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-3"],"frameId":null,"roundness":null,"boundElements":[{"type":"text","id":"shape-5"}],"updated":0,"link":null,"locked":false,"id":"shape-4","type":"rectangle","seed":333,"x":36,"y":178.2,"width":648.1750000000001,"height":654.8000000000001,"customData":{"revealStep":3}},{"angle":0,"strokeColor":"#394557","backgroundColor":"transparent","fillStyle":"solid","strokeWidth":1.5,"strokeStyle":"solid","roughness":0.7,"opacity":100,"version":1,"versionNonce":1,"isDeleted":false,"groupIds":["step-3"],"frameId":null,"roundness":null,"boundElements":null,"updated":0,"link":null,"locked":false,"id":"shape-5","type":"text","seed":406,"x":56,"y":196.2,"width":608.1750000000001,"height":618.8000000000001,"fontSize":17,"fontFamily":1,"text":"Problem: Tenant A runs a heavy report → slows DB for all\n\nLayer 1: Per-Tenant Rate Limiting (API Gateway)\n\nImplementation:\nRedis: INCR ratelimit:{tenant_id}:{minute} EX 60\nIf > limit → return 429 Too Many Requests\nResponse header: X-RateLimit-Remaining: 42\n\nLayer 2: Database Query Throttling\n• Per-tenant connection pool limits (Free: 2, Pro: 10, Ent: 50)\n• Query timeout per tenant (Free: 5s, Pro: 30s, Ent: 120s)\n• Statement timeout in PostgreSQL: SET statement_timeout = '5s'\n\nLayer 3: Resource Quotas\n• Storage quota per plan (Free: 1 GB, Pro: 50 GB, Ent: 5 TB)\n• Background job concurrency (Free: 1, Pro: 5, Ent: 50)\n• Webhook delivery rate (Free: 10/min, Pro: 100/min)\n\nLayer 4: Fair Scheduling (Background Jobs)\n• Per-tenant job queues with weighted fair queueing\n• Enterprise tenants get 10× weight vs Free\n• No tenant can consume > 20% of total worker capacity\n\nLayer 5: Circuit Breaker per Tenant\n• If tenant triggers > 100 errors/min → temporarily throttle\n• Prevents runaway automation / misconfigured integrations\n• Auto-recovers after error rate drops","originalText":"Problem: Tenant A runs a heavy report → slows DB for all\n\nLayer 1: Per-Tenant Rate Limiting (API Gateway)\n\nImplementation:\nRedis: INCR ratelimit:{tenant_id}:{minute} EX 60\nIf > limit → return 429 Too Many Requests\nResponse header: X-RateLimit-Remaining: 42\n\nLayer 2: Database Query Throttling\n• Per-tenant connection pool limits (Free: 2, Pro: 10, Ent: 50)\n• Query timeout per tenant (Free: 5s, Pro: 30s, Ent: 120s)\n• Statement timeout in PostgreSQL: SET statement_timeout = '5s'\n\nLayer 3: Resource Quotas\n• Storage quota per plan (Free: 1 GB, Pro: 50 GB, Ent: 5 TB)\n• Background job concurrency (Free: 1, Pro: 5, Ent: 50)\n• Webhook delivery rate (Free: 10/min, Pro: 100/min)\n\nLayer 4: Fair Scheduling (Background Jobs)\n• Per-tenant job queues with weighted fair queueing\n• Enterprise tenants get 10× weight vs Free\n• No tenant can consume > 20% of total worker capacity\n\nLayer 5: Circuit Breaker per Tenant\n• If tenant triggers > 100 errors/min → temporarily throttle\n• Prevents runaway automation / misconfigured integrations\n• Auto-recovers after error rate drops","textAlign":"left","verticalAlign":"middle","containerId":"shape-4","lineHeight":1.3,"autoResize":false,"customData":{"revealStep":3}}],"appState":{"viewBackgroundColor":"#fbfbf8","gridSize":null},"files":{}}