Performance and scaling

sections.operations

Performance and scaling

How Skrum holds up under load: p95 targets on hot paths, workspace-scoped read-through caching, and the chaos behavior when a dependency falls over.

Performance and scaling

Skrum is the all-in-one AI project control plane — team chat, tasks and sprints, native video meetings, and inbound code activity in one workspace, with every AI action waiting for a human yes.

Skrum is engineered to stay responsive when a workspace grows and when infrastructure has a bad day. This page documents the concrete numbers, the caching model, and the failure modes.

Load thresholds

Opt-in k6 scenarios under load/ hold Skrum to these targets against the composed stack with deterministic fake providers:

  • Realtime fan-out — 500 concurrent socket clients in one channel, p95 message-to-fanout latency ≤ 250 ms, error rate < 0.1%.
  • POST message — p95 ≤ 200 ms at 50 rps, error rate < 0.5%.
  • Board read (GET /api/tasks?projectId=…) — p95 ≤ 150 ms at 100 rps, error rate < 0.5%.
  • Search (GET /api/search) — p95 ≤ 300 ms at 50 rps, error rate < 1%.
  • Home summary (GET /api/home/summary) — p95 ≤ 200 ms at 100 rps, error rate < 0.5%.

Read-through caching

A small Redis-backed read-through cache covers three hot paths: the channel list per workspace, project board projections, and the dashboard/home summary. Every key is prefixed with the workspace accountId — a workspace can only ever read its own cached data. Invalidation is event-driven off the realtime spine (message.posted, channel.*, task.*), with a short TTL as a backstop. The cache stores only already-authorized, non-secret projections.

Chaos resilience

When a dependency falls over, Skrum fails closed rather than partial-writing or leaking data.

  • Redis down. Realtime and cache degrade; REST still serves the source of truth from Mongo and Postgres. Rate limiters fail safe (deny, never open the gate).
  • Mongo or Postgres unreachable. Routes surface a localized 503-class error — no unhandled crash, no partial write.
  • MinIO or LiveKit down. File uploads and meetings fail closed with a localized error; the rest of the app keeps working. See Backup and restore.

When a dependency returns, service resumes automatically — no manual restart required.

FAQ

  • Do I run the k6 suite in CI? Yes, behind an opt-in job. Load scenarios never gate a normal pull request.
  • Can I raise the cache TTL? The TTL is deliberately short. Event-driven invalidation is the primary correctness path; the TTL is only a Redis-outage backstop.
  • Does the cache ever leak across workspaces? No — every key is accountId-prefixed and a dedicated test proves cross-tenant isolation.

See also: Skrum documentation