Cassie is a single-node query engine for read models in CQRS and event-sourced systems. The event stream is the source of truth; Cassie materializes and serves projection data through PostgreSQL wire protocol, with a secondary administrative REST API.
Cassie uses cntryl-midge directly as its only storage layer. Midge provides persistence, durability, and recovery mechanics. Cassie provides SQL semantics, planning, execution, logical query layouts, indexes, search, analytics, resource controls, and query-visible errors.
- Documentation map
- Environment variables
- Feature behavior and status
- PostgreSQL wire and client contract
- Performance contracts
- Production-readiness evidence
- Future roadmap
- POC quickstart
cargo build --locked --bin cassie
cargo test --locked
cargo clippy --workspace --all-targets --all-features -- -D warnings -D clippy::pedantic
cargo fmt --all -- --checkRun the embedded proof of concept with:
cargo run --locked --example poc_read_modelFor benchmark navigation, compile all owners, run a short diagnostic suite, or run the normal Tier 1-4 developer suite:
cargo bench --locked --no-run --bench '*'
STRESS_PROFILE=smoke CASSIE_BENCH_SOAK_DURATION_SECONDS=5 cargo bench --locked --bench '*'
cargo bench --locked --bench 'tier[1-4]_*'The Tier 1-6 ownership, timing, fixture, evidence, and full-suite acceptance rules are canonical in Performance Contracts.
The Containers workflow publishes ghcr.io/cntryl/cassie as a multi-architecture
image. Every run receives its GitVersion SemVer tag and branch tag. A run from
main also updates latest, so a main build publishes the same manifest under
:<semver>, :main, and :latest.
compose.yml expects REST TLS to terminate at a trusted reverse proxy or load balancer. It binds the published ports to host loopback, sets CASSIE_ALLOW_INSECURE_NON_LOOPBACK_LISTEN=1 for the private container hop, and requires a non-default CASSIE_ROOT_PASSWORD for the fixed root login. Do not publish that plaintext hop directly to an untrusted network.
The provider-specific development profiles use the Sqrzl storage emulator. Copy
.env.example to .env, set CASSIE_ROOT_PASSWORD, and start one profile:
docker compose up -d # local disk storage
docker compose -f compose.s3.yml up -d # S3-compatible emulator
docker compose -f compose.azure.yml up -d # Azure Blob emulator
docker compose -f compose.gcs.yml up -d # GCS emulatorThe provider profiles pull ghcr.io/sqrzl/sqrzl-emulator:latest and connect to
it over the Compose network; the emulator is also published on host port 9000
for local diagnostics.
For Cassie to terminate REST TLS itself, remove the insecure-listener override, configure CASSIE_REST_TLS_CERT_FILE and CASSIE_REST_TLS_KEY_FILE inside the container, and mount the PEM certificate chain and private key read-only. Cassie fails closed when direct non-loopback TLS is selected but either file is absent.
When a trusted proxy terminates HTTPS, set CASSIE_REST_EXTERNAL_HTTPS=1 so Cassie emits HSTS and marks login and logout cookies Secure. Cassie does not trust Forwarded or X-Forwarded-Proto. This setting does not authorize a plaintext non-loopback listener: the private proxy hop still requires CASSIE_ALLOW_INSECURE_NON_LOOPBACK_LISTEN=1.
| Variable | Default | Contract |
|---|---|---|
CASSIE_AUTH_USER_ATTEMPTS_PER_MINUTE |
10 |
Process-local login token-bucket capacity per normalized user. |
CASSIE_AUTH_IP_ATTEMPTS_PER_MINUTE |
60 |
Process-local login token-bucket capacity per peer IP. |
CASSIE_AUTH_RATE_LIMIT_MAX_ENTRIES |
4096 |
Combined tracked user/IP entries; excess identities share bounded overflow buckets. |
CASSIE_REST_MAX_SESSIONS_PER_USER |
16 |
Active opaque REST sessions allowed for one normalized user; the global cap remains 1,024. |
CASSIE_REST_EXTERNAL_HTTPS |
0 |
Explicitly declares HTTPS outside Cassie for browser security attributes; forwarding headers remain ignored. |
CASSIE_EMBEDDINGS_MAX_RESPONSE_BYTES |
8388608 |
Maximum success or error response body accepted from a remote embedding provider. |
CASSIE_REST_WRITE_TIMEOUT_MS |
10000 |
REST transport write idle deadline. |
CASSIE_PGWIRE_WRITE_TIMEOUT_MS |
10000 |
Pgwire transport write idle deadline. |
Cassie targets predictable read-model queries: relational reads, indexes, full-text and vector retrieval, hybrid scoring, analytical projections, time-series access, and graph traversal. PostgreSQL compatibility exists to support familiar clients and SQL workflows; it is not a promise of full PostgreSQL parity.
Cassie's single-node boundary is permanent, not a pre-release omission. Cassie does not pursue distributed SQL, cluster management, membership, replication, consensus, sharding or rebalancing, cross-node transactions, multi-node query planning, remote query forwarding, OLTP optimization, trigger-based business logic, or a second storage abstraction. Deployments may run independent Cassie nodes, but external systems own routing, placement, failover, data movement, and fleet coordination.
