Performance Tuning
This page documents the operator-tunable knobs that affect Fleans throughput. For provider selection and full configuration reference, see Streaming and Persistence.
Stream provider sizing
Section titled “Stream provider sizing”Three knobs on KafkaStreamingOptions:
| Knob | Default | What it controls |
|---|---|---|
Fleans:Streaming:Kafka:QueueCount | 8 | Orleans-side pulling-agent count — one consumer per queue, each subscribed to one topic. Matches Redis:TotalQueueCount semantics. |
Fleans:Streaming:Kafka:ReplicationFactor | 3 | Per-topic broker replication, capped at the live broker count (1 on a single broker). |
Production deployments: SASL / TLS brokers are configured as in Kafka security; see Production-readiness gaps for what the adapter still leaves to you. Poison records can be routed to a dead-letter topic — see Streaming.
One knob:
| Knob | Default | What it controls |
|---|---|---|
Fleans:Streaming:Redis:TotalQueueCount | 8 | Orleans-side queue count for the Redis stream provider. Each silo’s pulling agents spread across this many queues. FIFO is guaranteed per stream; cross-instance traffic distributes across TotalQueueCount Redis queues. |
Redis streaming is supported via a third-party stream-provider package (not in-repo). Helm chart support for Redis streaming knobs is tracked in #610.
AzureQueue
Section titled “AzureQueue”QueueNames list length (default 8 entries). Tune by populating Fleans__Streaming__AzureQueue__QueueNames__0..N environment variables.
Persistence query pagination
Section titled “Persistence query pagination”User-task list query
Section titled “User-task list query”The user-task list query is paginated via Sieve and applies the assignee/candidate-group filter at the SQL level on PostgreSQL (via FromSqlInterpolated + JSON-text LIKE). The PostgreSQL path (PostgresUserTaskFilterStrategy) avoids materializing the full table. SQLite users with similar-scale workloads should switch to PostgreSQL via FLEANS_PERSISTENCE_PROVIDER=Postgres.
Event store reads
Section titled “Event store reads”EfCoreEventStore.ReadEventsAsync honors a configurable row limit. The default is MaxEventsPerLoad = 1000 (from FleansPersistenceOptions).
| Knob | Default | What it controls |
|---|---|---|
Persistence:MaxEventsPerLoad | 1000 | Maximum number of events loaded per grain-activation replay. A load past this limit throws, so the instance cannot activate until the limit is raised. The error says: “Increase Persistence:MaxEventsPerLoad if this is intentional.” |
Persistence:SnapshotInterval | 100 | A workflow instance snapshot (its full state) is written every this many events. Activation loads the snapshot and replays at most about this many events after it. Lower it for faster reactivation, raise it to write less. |
For typical workflow volumes, the defaults are appropriate. MaxEventsPerLoad must be greater than SnapshotInterval; the silo refuses to start otherwise. A failed snapshot write (log EventId 1131) is retried for about 8.5 minutes (1145 per failed retry, 1143 on success, 1144 when the retries give up); after that the instance’s next activation writes it. If snapshot writes keep failing, the event history after the last snapshot keeps growing. Fix the cause before it passes MaxEventsPerLoad, or raise the limit.
Related
Section titled “Related”- Streaming — provider selection and config matrix.
- Persistence — SQLite vs Postgres trade-offs.
docs/conventions/streaming.md— contributor-side tuning guide.