Performance Notes
This page collects what we know about running generated apps at scale. We have not benchmarked Morph end-to-end yet — treat numbers as informed estimates, not measurements.
Storage backends
The choice of <APP>_STORAGE dominates latency for entity-heavy workloads.
| Backend | Latency profile | Persistence | Concurrent writers |
|---|---|---|---|
memory |
sub-microsecond | none (lost on restart) | single process |
jsonfile |
full file rewrite per save | yes, on disk | single process |
sqlite |
typical SQL latencies; bun:sqlite is in-process | yes | single process unless WAL |
redis |
network round-trip per op | yes | many |
eventsourced |
replay from event store on read | yes | depends on event store |
Reach for sqlite for single-instance deployments, redis (or another networked store) once you horizontally scale.
jsonfile is intended for development only — it rewrites the entire file on every save. Don’t ship it.
Event store growth
The event store grows monotonically; nothing prunes old events by default. For long-lived deployments:
- Pick the right backend up front (
memoryfor tests,jsonfilefor dev,redisfor production). - If you build subscribers that replay history on cold start, expect that replay to lengthen as the store grows. Snapshot patterns aren’t generated yet — you’d build them in
impls/.
SSE and streaming
Generated APIs expose Server-Sent Events for any operation that emits domain events. SSE is a long-lived HTTP connection — sit it behind a reverse proxy that supports streaming (nginx, Caddy, Cloudflare with the right settings).
For multi-instance deployments, the in-memory event emitter doesn’t fan out across nodes. The redis event-store option uses Redis pub/sub for cross-instance broadcast, which is the right backend for >1 process.
Generation time
Generation is mechanical and fast — a 100-operation schema regenerates in seconds. The slow steps in regenerate:morph are TypeScript compilation and prettier, not Morph itself.
If you find generation taking >30s for a normal-sized schema, file a bug.
What we haven’t measured
- Real-world throughput numbers per backend.
- Memory footprint of a generated app at idle vs. under load.
- Effect runtime overhead — Morph leans on Effect for handler composition and DI; the cost is small but non-zero.
- Cold-start times for serverless deployments.
- SSE connection scaling beyond a few hundred concurrent clients.
If you benchmark anything in this list, please open an issue with the methodology and numbers — we’ll fold it in.