29 lines
1.4 KiB
Markdown
29 lines
1.4 KiB
Markdown
# Scaling & Provisioning
|
|
|
|
## Consumer Modes
|
|
|
|
The projection supports two JetStream consumption modes (configured via `PROJECTION_CONSUMER_MODE`):
|
|
|
|
- `single`: one durable consumer per projection process. Each message is processed once and the projection updates all `view_type`s defined in the manifest for that message.
|
|
- `per_view`: one durable consumer per `view_type`. Each consumer processes all events, but only updates its own `view_type` (checkpoint isolation and independent scaling).
|
|
|
|
In `per_view` mode, durable names are derived as:
|
|
|
|
`{PROJECTION_DURABLE_NAME}_{view_type}` (with non `[A-Za-z0-9_-]` replaced by `_`).
|
|
|
|
## Replica Scaling
|
|
|
|
To scale replicas, run multiple instances with the same durable name(s):
|
|
|
|
- `single` mode: all replicas share one durable consumer and work-steal messages from that consumer.
|
|
- `per_view` mode: all replicas share a durable consumer per `view_type`.
|
|
|
|
## Sharding
|
|
|
|
JetStream subject filtering does not support “hash/range shard by aggregate_id” on the consumer side.
|
|
|
|
If strict per-entity ordering is required across replicas, sharding must be encoded in the published subjects (for example `shard.<n>.tenant.<id>.aggregate.<type>.<id>`), and each shard must run with a matching `PROJECTION_SUBJECT_FILTERS` value.
|
|
|
|
Without subject-based sharding, multiple replicas can process events for the same `view_id` concurrently, which can break projections that depend on ordered read-modify-write updates.
|
|
|