Queries — Concept
A query is a named, parameterized read against one or more projection tables. You declare it in the DSL; the compiler produces a parameterized SQL template; the query service executes it at runtime.
Callers never write SQL. They call a query by name with typed inputs.
Why queries exist
The write path (actions → ledger) optimizes for correctness and per-entity ordering. It is not optimized for arbitrary read patterns — joins, filters, aggregates, leaderboards.
Projections materialize event data into PostgreSQL tables shaped for your read patterns. Queries are the typed API on top of those tables:
- Parameter validation before SQL runs
- Tenant isolation per fork (schema-scoped)
- Optional Redis caching
- No ad-hoc SQL in application code
Queries vs entity reads vs projections
| Mechanism | What it reads | Consistency |
|---|---|---|
| Entity read API | Current entity snapshot from runtime | Strong — immediately after write |
| Projection table | Materialized rows from events | Eventual — lags ledger by ms–seconds |
| Named query | Compiled SQL over projection(s) | Eventual — same as underlying projection |
After submitting an action, a projection query may not reflect the write yet. Design callers for eventual consistency, or use the entity read API when you need the latest snapshot.
How execution works
- Client calls the query endpoint with
paramsmatching the declaredinputschema. - Query service resolves the active IR version for the fork.
- It loads the compiled SQL template and binds parameters.
- Optional Redis cache check (if
cache_ttl_secondsis set). - SQL executes in the tenant schema
{platform}_{app}_{fork}. - Results return as JSON.
Where queries live in your app
# app.causet
includes:
queries: [./queries/**/*.queries.causet]Each .queries.causet file declares named queries under the queries: key. Queries reference projection table names from your projections: definitions — they cannot query arbitrary SQL tables.
IR-compiled, not hand-written SQL
The compiler validates that:
fromreferences a declared projection tableinputtypes match filter parameters- Joins connect projection-to-projection only
- Aggregate queries include
group_by
At deploy, the SQL template is baked into causet.projections.json. Changing a query requires a new release.
Next steps
- Overview — guide map for this section
- Defining Queries — syntax,
from,input,fields - Examples — concert-app query catalog