SET or JSON.SET; the realtime provider appends events
to Redis Streams for WebSocket and GraphQL subscribers.
Requirements
The current connector test matrix uses Redis 7.4 for string documents and Redis Stack 7.4 for RedisJSON documents. The configured identity must be able to run the commands listed under ACL permissions. VentStream supports a standalone or managed primary endpoint, Redis Sentinel, and Redis Cluster. Choose the matching endpoint topology so failover and routing are handled with the correct Redis protocol.Preflight a deployment
Run an online check with the same configuration and secret references the engine will use in production:Inspect materialization drift
Use the read-only drift check to inspect the bounded Redis structures owned by one or more routing targets:fixed and views routing derive their targets from configuration. Supply
--redis-target for by_output_relation and by_projection_target, where the
set of target names is data dependent. The default scan limit is 100,000 keys
per target and key class; set a lower bounded limit when checking a large
keyspace:
complete: false means the scan reached its limit;
it is not a clean result. The command does not claim a writer or change Redis.
This structural check cannot discover a source row that is absent from both the
Redis value and its metadata. Compare the report with the authoritative source
before declaring parity. For a stable incident snapshot, drain the pipeline
before inspection. If requires_rebootstrap is true, rebuild the exclusively
owned target from its source rather than deleting individual metadata keys.
Configuration
redis:// for an unencrypted local endpoint and rediss:// for TLS with a
publicly trusted certificate. Keep credentials in environment variables or a
mounted secret provider rather than embedding them in the URL or YAML.
For credentials that must rotate without restarting the engine, point the auth
references at mounted files:
#insecure URL mode. Apply CA, client certificate, or client key changes with a
rolling engine restart. Mounted ACL username and password files use the live
rotation behavior described above.
Key construction
Every key has this form:ventstream:orders:production:{orders}:*. current is the renewable lease.
lineage is a non-expiring witness for the latest process token. If failover
outlasts the lease, the same process can recover ownership only while the
lineage remains unchanged. A process replaced by a newer writer stays fenced
even after the replacement lease expires. Do not modify either key.
RedisJSON cache writes also use a short-lived staging key outside the data-key
pattern. The engine sets the JSON value and TTL on that key, then renames it
into place so a failed expiry cannot expose a replacement value without its
cache TTL.
Routing strategies:
Use a unique prefix for each pipeline and environment. VentStream maintenance
operations must never share a prefix with application-owned keys.
Lookup views
Useviews when application access patterns need keys derived from document
fields rather than source primary keys. A single source event can update
multiple views atomically:
source.relation selects a raw table, collection, label mapping, or topic
relation. source.projection_target selects target.index from a PostgreSQL or
MySQL joins spec. Define exactly one selector per view. source.namespace is
optional and narrows a relation to one logical source namespace.
Key templates support:
All placeholders must resolve by default. Set
key.on_missing: skip only when
the intended behavior is to remove the source document’s previous entry from
that view and omit its replacement. JSON key pointers must resolve to a string,
number, or boolean; null, arrays, and objects are not valid key segments.
Filters combine conditions with mode: all by default; mode: any is also
available. Conditions support equals, not_equals, in, not_in, exists,
and not_exists. Comparisons operate on JSON scalar values. A missing pointer
does not match equals or in; it does match not_equals and not_in. Pair a
negative comparison with exists when the field must be present.
value.mode can store the complete document, one pointer, or a named
fields object.
VentStream keeps a source manifest and target ownership record for every
materialized entry. An update that changes a derived key removes the old key
and writes the new key in the same fenced Lua operation. A filter transition,
source delete, or truncate removes every entry previously owned by the affected
source document even when the delete event has no document payload. Runtime key
collisions block the batch before any view is changed. Within one batch, source
event order also governs key handoff: a document may claim a key only after its
current owner has released it.
View routing requires keyspace.ownership: exclusive. VentStream stores a
non-expiring schema fingerprint and target inventory below the configured
prefix. Changing a view selector, key, filter, value, document format, or
retention contract requires a controlled drain/rebootstrap. Reordering
unchanged view declarations does not. Rebootstrap clears targets removed by the
new configuration as well as targets still present, then installs the new
fingerprint before snapshot delivery resumes.
View transformation errors fail closed instead of entering the DLQ because
skipping one update could leave an older key visible. This includes malformed
JSON, unresolved required pointers, missing stable document IDs, size-limit
violations, and ownership metadata conflicts.
Keyspace ownership
keyspace.ownership: shared is the default. It permits deterministic point
upserts and deletes but rejects target-wide cleanup before changing the source
cursor or Redis. Use it when another pipeline or application may write below
the same prefix.
Set keyspace.ownership: exclusive only when this pipeline is the sole writer
for every routed target below its prefix:
Value format
document.format: string stores the compact JSON payload as a Redis string
using SET.
document.format: json uses RedisJSON JSON.SET. The engine checks for
JSON.SET during startup when the ACL permits command inspection and fails
closed if the module is unavailable. JSON cache writes apply the value and TTL
atomically.
Retention contract
Use a materialized view when Redis is the retained read model:maxmemory-policy noeviction for materialized views. Silent key eviction
would make the Redis view incomplete. The same policy gives caches the most
predictable writer availability: cache entries still expire at their configured
TTL, while memory pressure backpressures new writes instead of selecting the
expiring writer lease. A volatile-* policy may also evict that lease.
VentStream can recover it when the durable lineage is unchanged, but repeated
lease eviction creates avoidable retry and readiness churn.
Use cache mode for rebuildable entries:
materialized_view
when Redis must retain every current source record until an explicit delete,
truncate, or rebuild.
Each upsert refreshes the TTL. Deletes remove the key immediately.
Acknowledgement
mode: primary advances after the primary applies the ordered pipeline.
mode: replicated issues WAIT on the same connection after the pipeline and
requires the configured number of replica acknowledgements before source
progress can advance:
WAIT confirms replication, not disk persistence. Configure Redis persistence
and failover according to the recovery point the materialized view requires.
If the acknowledgement target is not met, VentStream keeps retrying with
backpressure and does not send the batch to the DLQ.
mode: aof uses Redis 7.2 or later
WAITAOF on the same connection as the
materialization write. It can require the writable primary, replica AOFs, or
both to fsync before source progress advances:
WAITAOF or a
primary without required AOF persistence is a deployment error. WAITAOF
improves durability but does not make asynchronous Redis replication strongly
consistent during every failover.
Set response_timeout_ms to at least acknowledgement.timeout_ms; validation
rejects a shorter command timeout.
Endpoint topology
Configure exactly one ofendpoint_ref or topology.
Standalone or managed endpoint
Useendpoint_ref for one writable Redis endpoint or a managed endpoint that
follows the provider’s current primary:
Redis Sentinel
Sentinel topology discovers and verifies the writable primary for a named Sentinel service:service_name, verifies the returned node is a primary, and
rediscovers after connection loss, a read-only response, or a temporary
election gap. Configure multiple Sentinel endpoints from separate failure
domains. Sentinel endpoint URLs must use Redis database 0.
sentinel_auth and sentinel_tls protect Sentinel connections. The top-level
auth and tls blocks protect the discovered Redis data-node connection. Set
data_node_tls: true when the discovered nodes require TLS, including when
top-level data-node trust or client-certificate files are configured.
Sentinel must advertise addresses reachable from the VentStream process. For
TLS deployments it should advertise hostnames covered by the data-node
certificate; an IP address absent from the certificate’s subject alternative
names will fail hostname verification.
Redis Cluster
Cluster topology accepts a bounded list of initial nodes and discovers the complete hash-slot map:MOVED, and follows one-shot ASK redirects with
ASKING. Cluster nodes must advertise addresses reachable from the VentStream
process. For TLS clusters, every configured and advertised hostname must match
the node certificate. Cluster endpoint URLs must use Redis database 0.
A source batch may contain several targets. VentStream splits it into one
ordered, fenced operation per target so Lua never crosses hash slots. Progress
advances only after every target operation succeeds. Replicated and AOF
acknowledgement run against each target’s owning primary and report the lowest
observed acknowledgement counts.
During an active slot migration, Redis may accept single-key commands through
ASK while rejecting a target’s multi-key Lua operation with TRYAGAIN until
slot ownership converges. VentStream keeps the source backpressured and retries;
it does not send the event to the DLQ or advance the source checkpoint.
Cluster topology supports at most one declarative lookup view. Multiple views
for one source event can map to different hash slots and cannot be updated
atomically by Redis. Direct routing remains supported across any number of
targets. RedisJSON must be installed on every primary that may own a target
slot.
Writer fencing
Each process acquires a renewable lease independently for every target it first modifies. Active writers renew idle leases in the background and before each mutation. A duplicate process cannot overwrite an active lease; it remains backpressured without changing Redis or advancing its source checkpoint. After an ungraceful exit, the next writer can acquire the target when the lease expires. The default lease is 30 seconds. Each lease has a durable lineage witness. When a primary or network outage lasts longer than the lease, a process may recreate its lease only if no newer writer has changed that lineage. This allows automatic failover recovery without allowing a superseded process to reclaim a target. Give each deployment revision a stable writer identity. Fleet deployments use their deployment ID automatically. A standalone deployment should setwriter.id_ref or VS_REDIS_SINK_WRITER_ID.
For an intentional handoff that must not wait for lease expiry, identify both
the new writer and the expected previous writer:
takeover_from_ref. A stale handoff therefore cannot evict an unexpected
writer. Stop or drain the previous deployment before using this setting. Every
write and target cleanup still verifies the lease generation before changing
data. Targets below the same prefix are independent, so handing off orders
does not change ownership of customers.
Fencing coordinates VentStream processes that use the same prefix and target.
It does not prevent an application, script, or another Redis client from
changing those keys directly. A prefix declared exclusive must not have
external writers.
In Fleet-managed mode, a restarted supervisor also keeps the engine stopped
until it acquires the current control session and receives convergence work.
An already-running engine may continue through a temporary control-plane
outage; if Fleet later admits a replacement, Redis fencing prevents the older
process from overwriting the replacement.
ACL permissions
The Redis identity needs access only to its configured key prefix. Required commands are:PING,GET,SET,DEL,PEXPIRE,EVALSHA, andSCRIPT LOADfor writer-leased materializationHGET,HSET, andEXISTSfor lookup-view manifests and ownership checksSCANandUNLINKfor target cleanup after a source truncate or controlled rebuildWAITwhen replicated acknowledgement is enabledWAITAOFwhen AOF acknowledgement is enabledROLEand, as a compatibility fallback,INFO REPLICATIONfor Sentinel-discovered data-node role verificationCLUSTER SLOTSfor Cluster slot discovery and refreshCLUSTER KEYSLOT,CLUSTER MYID, andCLUSTER NODESwhen exclusive ownership permits target cleanup; these checks prevent a node-localSCANfrom running across a slot ownership changeJSON.SETfor RedisJSON documentsTYPE,PEXPIRE, andRENAMEfor RedisJSON cache entriesCOMMAND INFOis optional; without it, RedisJSON support is verified on the first write
sentinel_auth also needs
SENTINEL MASTERS. Keep Sentinel and data-node ACLs separate when the
deployment uses different identities.
An ACL command denial is a permanent configuration error. Static authentication
failures also block. Authentication failures from mounted credential files
remain backpressured and retryable so credential rotation does not require an
engine restart. None of these failures advances the source checkpoint.
Truncate handling
PostgreSQLTRUNCATE is handled without loading the target keyspace into
memory. VentStream scans one routed target in bounded pages and deletes keys
with UNLINK. A transient failure restarts the idempotent cleanup and keeps
source progress behind the truncate.
by_output_relationclears only the truncated relation.by_projection_targetis supported for SQL-mode projections because the denormalizer emits an explicit target-scoped clear before rebuilding current rows.viewsclears every matching view target. Source manifests and target ownership records are removed with the materialized keys.- Truncating a related table in PostgreSQL SQL mode recomposes the affected projection in bounded primary-key pages.
fixedrouting rejects raw truncate events because multiple relations may share the target.
Reliability
- Each bounded batch verifies its target generations and applies its ordered writes in one Lua invocation without interleaving from other Redis clients.
- Dispatcher batches are issued serially because Redis values do not carry a source-version guard. This prevents a slower, older batch from overwriting a newer value while still allowing up to 1,000 ordered commands per Lua call.
- RedisJSON cache replacements become visible only after the staged value has its TTL.
- Batches are split at the configured byte boundary without changing event order. One Lua invocation is also capped at 1,000 commands to limit Redis event-loop occupancy when upstream batches contain many small records.
- Upserts and deletes are idempotent because every event carries a stable document ID.
- Connection loss, timeout, loading, capacity pressure, persistence pressure, replica availability, failover, read-only, and cluster-down responses retry with capped exponential backoff and jitter.
- Authentication, ACL, invalid topology configuration, and unknown command failures block delivery without advancing the source checkpoint.
- Target cleanup uses bounded
SCANpages andUNLINKbatches. It preserves write-before-truncate and write-after-truncate ordering. - Cluster cleanup verifies the routed primary and slot state before and after the node-local scan. Resharding or an ownership change retries the complete, idempotent cleanup.
- With direct routing, invalid JSON, malformed key headers, configured key- or value-size violations, and a RedisJSON wrong-type conflict identify the exact event and use the DLQ path. Lookup views fail closed on transformation errors so an older materialization cannot remain visible while source progress advances.
/readyzreflects sustained transient sink failure and immediate permanent blockers through the shared sink-health gate.- A superseded writer fails closed. A missing or expired current lease is recovered only when its durable lineage still belongs to the same process; otherwise a new process must acquire the target.
Safety limits
Redis sink limits are validated before the connector opens a socket:
With direct routing, records that exceed a configured key or value limit, or
whose complete command cannot fit within
max_batch_bytes, are identified
exactly and follow the DLQ path. Lookup views block the pipeline on the same
violations.
Lookup-view configuration is also bounded:
View key rendering and selected-value serialization enforce these limits while
they write. A field projection cannot duplicate a large JSON subtree beyond the
configured value or batch limit before the pipeline rejects it.
SQL projections
PostgreSQL and MySQL SQL-mode projections use an optional OpenSearch reverse lookup to recover a parent after a 1:many child delete whose source pre-image does not contain the parent key. Redis pipelines must disable that lookup:REPLICA IDENTITY FULL or a
suitable replica-identity index for those child tables. MySQL joined
projections require binlog_row_image=FULL so deletes and reparenting contain
the previous parent key. Direct publication tables and projections without that
delete dependency do not need a sink lookup.
Environment-only configuration
Canonical YAML is preferred. The equivalent sink-specific variables are:
Lookup views are configured only through canonical YAML because their
selectors, templates, filters, and values form a versioned data contract.