Queries API
The causet-query-service (port 8082) serves named queries defined in the DSL. Queries run against projection tables in PostgreSQL. Results are cached in Redis by query name and parameter key.
Execute a Named Query
POST /v1/platforms/{platformId}/applications/{applicationId}/forks/{forkId}/queries/{queryName}
Host: causet-query-service:8082
Content-Type: application/jsonPath parameters:
| Parameter | Type | Description |
|---|---|---|
platformId | string | Platform identifier |
applicationId | string | Application identifier |
forkId | string | Fork (e.g. "main") |
queryName | string | Query name as defined in the DSL |
Request body:
{
"params": {
"user_id": "user-1"
}
}Provide all input: parameters declared as required: true in the DSL. Optional parameters may be omitted.
Response:
{
"rows": [
{
"show_id": "show-pj-brooklyn-2026",
"artist_id": "artist-pearl-jam",
"title": "Pearl Jam - Dark Matter Tour",
"venue": "Barclays Center",
"date": "2026-09-15"
}
],
"count": 1
}| Field | Type | Description |
|---|---|---|
rows | array | Result rows |
count | integer | Total number of rows returned |
Example:
curl -X POST \
"http://localhost:8082/v1/platforms/my-platform/applications/concert-app/forks/main/queries/shows_for_followed_artists" \
-H "Content-Type: application/json" \
-d '{ "params": { "user_id": "user-1" } }'Read Entity State
Retrieve the current state of a specific entity directly.
GET /v1/platforms/{platformId}/applications/{applicationId}/entities/{entityType}/{entityId}
Host: causet-query-service:8082Path parameters:
| Parameter | Type | Description |
|---|---|---|
platformId | string | Platform identifier |
applicationId | string | Application identifier |
entityType | string | Entity type as defined in the DSL state: block |
entityId | string | Entity identifier |
Response:
{
"entityType": "user",
"entityId": "user-1",
"fields": {
"username": "alice",
"following_count": 3
},
"cursorVersion": 7,
"lastEventAt": 1719360000000
}Note: Entity state is read from the ledger (event store), not from projection tables. It reflects the authoritative accumulated state, not any derived projection.
Pagination
The maximum rows returned by a query is governed by the limit: field in the DSL query definition:
queries:
shows_for_followed_artists:
...
limit: 50Proposed: Offset-based pagination via
params.offsetis on the roadmap. Currently, thelimit:value in the DSL is the hard ceiling — there is no runtime pagination parameter.
Caching
Query results are cached in Redis. The cache key is derived from:
- Query name
- Resolved parameter values
- Fork ID + tenant schema
Cache invalidation is TTL-based. There is no explicit invalidation on projection write. Configure TTL via the QUERY_CACHE_TTL_SECONDS environment variable on the query service (default: 30 seconds).
| Behavior | Detail |
|---|---|
| Cache hit | Returns cached result; does not query PostgreSQL |
| Cache miss | Queries PostgreSQL, caches result, returns rows |
| TTL expiry | Next request re-queries PostgreSQL |
| Projection lag | Data may be stale by up to projection_lag + cache_TTL |
Note: For read-after-write consistency in high-frequency workflows, set
QUERY_CACHE_TTL_SECONDS=0to disable caching. This increases PostgreSQL load.
Control Plane Proxy
The control plane (causet-cloud-control-plane, port 3000) proxies query requests through its Next.js API routes:
POST /api/v1/platforms/{platformId}/applications/{applicationId}/forks/{forkId}/queries/{queryName}This proxy adds Clerk authentication and forwards to the query service. The request/response shape is identical.
Error Codes
| HTTP Status | Code | Description |
|---|---|---|
| 400 | QUERY_NOT_FOUND | The query name does not exist in the active IR for this fork |
| 400 | INVALID_PARAMS | A required parameter is missing or has the wrong type |
| 404 | SCHEMA_NOT_FOUND | The tenant schema does not exist — the fork has not been deployed |
| 503 | SERVICE_UNAVAILABLE | PostgreSQL or Redis is unreachable |
Error response body:
{
"error": "QUERY_NOT_FOUND",
"message": "Query 'shows_for_followed_artists' not found in active IR for fork 'main'",
"queryName": "shows_for_followed_artists",
"forkId": "main"
}Health Check
GET /actuator/health
Host: causet-query-service:8082Response:
{
"status": "UP",
"components": {
"db": { "status": "UP" },
"redis": { "status": "UP" }
}
}