Skip to content

Performance results

Measured on 2026-11-13 on the development machine (Ryzen 7, 16 threads, local PostgreSQL 17), release build, one process running every role unless stated. The scripts are in tests/e2e in the repository.

The targets were set before the first slice was built, on one core with a warm cache.

Path Target Measured
Delivery, content by path p99 under 5 ms p50 0.09 ms, p99 0.22 ms (2,000 sequential requests, one connection)
Delivery, conditional GET (304) p99 under 1 ms p50 0.09 ms, p99 0.22 ms
Cold start to first served request under 500 ms 13–25 ms (authoring, projector and delivery roles; measured at the first slice)
Resident memory, idle under 60 MB 28.5 MB with every role, after all scenarios; 9 MB with authoring, projector and delivery only
Image rendition, 4000 px JPEG to 1200 px WebP under 150 ms 105 ms median; to JPEG 51 ms
Editor, initial JavaScript under 250 kB gzipped 173 kB
Authoring save and publish latency p99 under 30 ms and 50 ms Not measured separately

The binary is 30 MB.

How. No ORM, prepared statements, a schema snapshot shared by reference, responses written straight from stored JSON where the shape allows, and the ETag computed at projection time. Renditions are pure Rust plus libwebp built from bundled source, off the async threads on a bounded pool; WebP encoding is about half of the 105 ms.

  • seeamess-migrate verify against a live Optimizely CMS 12: 12 responses compared, no unexpected differences. One documented difference: Optimizely shows its global assets folder under a UI display string.
  • The existing front-end renders the same visible text from either CMS for all six demo pages.
  • After adopt, all delivery responses are byte-identical to before.

Authoring, projector and delivery as three processes on one database, outbox poll 250 ms:

  • A publish is visible on the delivery process after 245 ms (median of 20).
  • Delivery keeps answering with the authoring process stopped.
  • Two projectors do not double-apply.
Measure Result
First sync 40 s (about 500 contents per second)
Repeat sync, nothing changed 8 s, no outbox growth
Engine memory after sync 35 MB
Route lookup p50 0.11 ms, p99 0.24 ms
Search, rare term / common term 12 ms / about 100 ms
Subtree delete 2.3 s, grows engine memory by about 65 MB
Restore of that subtree 10 s, grows engine memory by about 50 MB
Purge of that subtree 1.1 s
  • Deleting or restoring a very large subtree holds one event per content in memory and projects inline. It is correct but heavy; moving those events and projection changes into SQL is the fix.
  • Search has no ranking, and a common term costs about 100 ms at this size.
  • The S3 blob backend is tested against an in-memory object store, not a real S3 service.
  • No AVIF output.
  • Preview tokens unlock referenced media one level deep.