sync-topic
Sync Topic
Typed event streams. Server version uses Redis Streams, browser version uses an in-memory event log. Two consumption modes: reader (consumer groups, at-least-once, commit-based) and live (stateless fan-out/replay).
Decision Guide: reader() vs live()
- reader(group): durable, at-least-once. Each group tracks its own cursor. Call
commit()after processing. Use for event-driven workers (mailer, projections, analytics). - live({ after }): stateless fan-out. No group state, no commit. Use for real-time dashboards, debugging, or replay from
"0-0".
Decision Guide: topic vs queue
- topic: events are broadcast to all consumer groups independently. No ack/nack per message — use
commit(). Best for fan-out, event sourcing, audit. - queue: work items are distributed to exactly one consumer. Use
ack()/nack()per message. Best for task distribution, job pipelines. Seesync-queueskill.
Gotchas
commit()is per-delivery, not per-batch. Always commit after processing each event.- Invalid payloads on the read path are auto-acknowledged and skipped (logged, not thrown).
reader().stream({ wait: true })auto-retries transient errors. Do not wrap withretry().
More from valentinkolb/sync
sync-job
Use this skill when implementing durable background jobs with @valentinkolb/sync job: defining typed process handlers with ctx.step/ctx.heartbeat/ctx.signal, submit/join/cancel flows, idempotent submission via key, retries with exponential backoff, lease timeouts, and per-job event streams for audit. Also use when choosing between job (durable execution with state) vs queue (simple work distribution). Also works in the browser via `@valentinkolb/sync/browser` with in-memory state — same API, no Redis needed.
9sync-retry
Use this skill when handling transient transport failures with @valentinkolb/sync retry utility: wrapping Redis/network calls with exponential backoff, configuring per-call retry overrides, using AbortSignal for cooperative cancellation, and classifying errors with retryIf. Also use when writing stream reader loops that must survive brief outages. Works identically in the browser via `@valentinkolb/sync/browser` — no Redis dependency, uses setTimeout-based sleep.
9sync-ephemeral
Use this skill when implementing short-lived typed state with @valentinkolb/sync ephemeral: TTL-based key/value with upsert/touch/remove, snapshot-plus-cursor reconciliation for cache hydration, streaming upsert/touch/delete/expire events, capacity/payload limits, and presence-style use cases where entries should naturally expire. Also works in the browser via `@valentinkolb/sync/browser` with in-memory state — same API, no Redis needed.
9sync-scheduler
Use this skill when implementing distributed cron scheduling with @valentinkolb/sync scheduler: registering idempotent schedules across pods, leader-fenced dispatch via job.submit, misfire policy (skip/catch_up_one/catch_up_all), triggerNow for manual dispatch, unregister, metrics/health, and multi-pod leader election. Depends on sync-job for execution and sync-mutex for leader lock. Also works in the browser via `@valentinkolb/sync/browser` for single-tab cron scheduling — same API, no Redis needed.
9sync-mutex
Use this skill when working with @valentinkolb/sync distributed locks: exclusive critical sections across pods with withLock/withLockOrThrow, manual acquire/release, lease extension for long work, retry tuning, owner-safe release via Lua, and LockError handling. Also works in the browser via `@valentinkolb/sync/browser` with an in-memory store for single-tab lock coordination.
9sync-ratelimit
Use this skill when working with @valentinkolb/sync rate limiting in Bun/TypeScript: creating per-identifier sliding-window limiters, choosing check() vs checkOrThrow(), handling RateLimitError with resetIn/Retry-After headers, tuning window size, and reasoning about Redis key layout. Also works in the browser via `@valentinkolb/sync/browser` with an in-memory store — same API, no Redis needed.
9