Skip to content

Sinks

A sink is where Wallaby delivers your transformed documents. Wallaby ships sinks for Meilisearch, Elasticsearch, OpenSearch, Kafka, pgvector and HTTP webhooks, and you can deliver anywhere else by implementing ISink.

A single Wallaby host can run several sinks at once. They share one replication slot and one publication, so adding a second destination costs no extra load on Postgres.

Choosing a destination

DestinationPackageReach for it whenNativeAOT
MeilisearchWallaby.Sinks.MeilisearchFast typo-tolerant product or in-app searchno (client SDK)
ElasticsearchWallaby.Sinks.ElasticsearchSearch plus analytics, self-managed or Elastic Cloudno (client SDK)
OpenSearchWallaby.Sinks.OpenSearchAWS-managed search (Amazon OpenSearch Service)no (client SDK)
KafkaWallaby.Sinks.KafkaFanning changes out to other servicesyes
pgvectorWallaby.Sinks.PgvectorA RAG corpus that stays inside Postgresyes
HTTPWallaby.Sinks.HttpAnything that exposes an endpointyes
Customn/aEverything elseyour call

Meilisearch, Elasticsearch and OpenSearch depend on client SDKs that are not trim- or NativeAOT-safe. All other packages are marked IsAotCompatible. See each page's NativeAOT section for the SerializerOptions a trimmed host needs.

If you are keeping embeddings fresh rather than building a search index, start at RAG & Embeddings, which covers when to let the destination own embedding and when to do it in the sink.

Sink guarantees

These apply to all sinks regardless of what you pick:

  • At-least-once delivery. The replication slot only advances after a batch is durably delivered, so a crash can redeliver the last batch. Every built-in sink upserts and deletes by a stable document id.
  • Commit order. Changes are delivered in the order Postgres committed them, and batches that get split into several requests preserve that order.
  • One slot, one ack point. Every sink on a host reads the same replication stream. Wallaby only acknowledges once the batch has reached all of them.
  • Backfill seeding. A new destination is seeded by backfill, which runs concurrently with the live stream and merges with it, so there are no gaps and no stale overwrites.
  • Purge-then-backfill. Bumping a mapping's backfill version with purgeOnChange: true empties the destination before rebuilding it, which is how you reshape a document or re-embed a corpus.
  • Permanent failures halt the pipeline. A misconfiguration or a payload the destination will never accept stops the pipeline rather than silently skipping records. Transient failures retry with exponential backoff.

Future plans

There is no built-in sink for Typesense, Algolia, Redis, MongoDB or SQL Server, although these are planned for the future. Any of them is reachable today through a custom ISink, which is a small interface, and sink contributions are welcome.

Write your own

Custom sinks covers the ISink contract: batch delivery, how to classify a failure as retryable or permanent, one-time setup, and purge support.

Released under the Apache 2.0 License.