Kaptanto logoOpen source — Apache 2.0 — v0.3.0

Turn every database write into a real-time event.

kaptanto captures every insert, update, and delete from Postgres and MongoDB the moment it happens — stdout, SSE, gRPC, webhook, vector, or broker sinks (NATS, SQS, Kafka, Pub/Sub, RabbitMQ). Optional MCP server, HTTP enrichment, and YAML actions for AI-native pipelines. One static binary. Deploys anywhere.

kaptanto
# stream order changes to your services
$ kaptanto --source postgres://prod:5432/fintech \
--tables orders,payments --output stdout
{"operation":"insert","table":"orders","after":{"id":1234,"status":"pending","amount":149.90}}
{"operation":"update","table":"orders","after":{"id":1234,"status":"settled","amount":149.90}}
{"operation":"insert","table":"payments","after":{"id":5678,"order_id":1234,"method":"pix"}}
INSERTorders #4821UPDATEusers #119INSERTpayments #7703DELETEsessions #3321UPDATEorders #4822INSERTinvoices #902UPDATEinventory #445DELETEtokens #8812INSERTaudit_log #15590UPDATEaccounts #77INSERTtransfers #3320UPDATEshipments #663INSERTorders #4821UPDATEusers #119INSERTpayments #7703DELETEsessions #3321UPDATEorders #4822INSERTinvoices #902UPDATEinventory #445DELETEtokens #8812INSERTaudit_log #15590UPDATEaccounts #77INSERTtransfers #3320UPDATEshipments #663
Features
Production CDC. Minus the complexity.
Backfills, crash recovery, per-key ordering, and HA — built in. Nothing extra to operate.
latency

Low-latency streaming

Events flow from the WAL as each transaction commits. Burst p50 latency: ~3.5s at ~2.3k eps for the default Go build (2.3s with the optional Rust FFI build). No polling interval.

schema

One event schema

The same JSON format across every source. Write your consumer once and connect to any database.

checkpoint

Crash-safe cursors

Per-consumer positions persist on every event. Reconnect and resume from exactly where you stopped.

backfill

Consistent backfills

Snapshot and stream run concurrently. Watermark coordination prevents stale or duplicate rows.

ordering

Per-key ordering

Events for the same primary key always arrive in commit order. Slow consumers never block other partitions.

ha

Built-in HA

Two instances, one leader. Advisory lock election — session-scoped, no clock skew, ~5-second failover.

sinks

Ten output modes

stdout, SSE, gRPC, webhook, vector, and five broker sinks — NATS, SQS, Kafka, Pub/Sub, and RabbitMQ. At-least-once delivery with per-key ordering end-to-end.

ai

Actions & AI-native

Route CDC to webhook actions, optional MCP subscriptions with ACL, and fail-open HTTP enrichment that attaches opaque ai_context before durable append.

routing

Per-table routing

Route events from different tables to different topics or queues via a Go template — cdc.{{.Schema}}.{{.Table}}.

Use Cases
Built for event-driven pipelines at product scale.
Best fit: notification fan-out, search index sync, cache invalidation, audit trails. Up to ~3.5k eps large-batch throughput.
notify

Notification pipelines

Order inserted → push notification fan-out in seconds (burst p50 ~3.5 s in the published shared-CPU benchmark; ~2.3 s with the Rust FFI build). No polling, no webhook delay.

search

Live search sync

Product catalog change → Elasticsearch or Typesense index update within seconds, automatically.

cache

Cache invalidation

Row updated → Redis key evicted before the next read hits the database. Consistent by design.

audit

Audit trail

Every insert, update, and delete captured in order, with idempotency keys. Append-only and crash-safe.

Compatibility
Works with the databases you already run.

Database sources

PG
PostgreSQL
WAL logical replication · v14-17
MG
MongoDB
Change Streams · v4.0+
MY
MySQL soon
binlog · GTID

Output modes

>
stdout
NDJSON · pipe anywhere
SE
Server-Sent Events
HTTP · auto-reconnect · Last-Event-ID
gR
gRPC Stream
Protobuf · HTTP/2 · backpressure

Queue sinks v0.2.0

NA
NATS JetStream
at-least-once · PubAck · per-table subjects
SQ
AWS SQS FIFO
MessageGroupId ordering · mTLS · per-table queues
KF
Kafka
franz-go · SASL/TLS · record key ordering
PS
Google Pub/Sub
ordering key · ResumePublish · TopicTemplate
RQ
RabbitMQ
AMQP · publisher confirms · auto-reconnect
Get started
From install to streaming in 90 seconds.
1
Install
$ curl -fsSL https://get.kaptan.to | sh
2
Run — point at your database
$ kaptanto \
  --source postgres://localhost:5432/mydb \
  --tables orders,payments \
  --output stdout

Use --output sse or --output grpc for multi-consumer setups. Use --output nats|sqs|kafka|pubsub|rabbitmq to push directly to a queue. All of these require --auth-token (or --insecure for local dev) — see the Configuration docs.

3
Events stream out — one JSON line per change
{"operation":"insert","table":"orders","after":{"id":1,"status":"pending","amount":49.99}}
{"operation":"update","table":"orders","before":{"status":"pending"},"after":{"status":"shipped"}}
{"operation":"delete","table":"payments","key":{"id":88}}

Pipe to jq, a webhook, a queue, or anything that reads stdin.

Why kaptanto
A complete CDC stack that fits in a single binary.
ToolReal-timeNo KafkaMulti-DBSingle binaryFreeMin cost
kaptanto$0
Debezium$0+Kafka
Confluent~~$200/mo
Fivetran~$12K/yr
Estuary$0
AWS DMS~$70/mo
Changelog
What changed and when.
v0.3.0Jul 2026Security & Correctness
  • Bearer-token authentication for the SSE and gRPC data plane — auth-token config or KAPTANTO_AUTH_TOKEN env var, enforced on every network output; --insecure opts out with a startup warning
  • Server-side TLS and mTLS for inbound SSE and gRPC (server-tls), separate from per-sink outbound TLS
  • Postgres fails closed when no tables are configured — capturing everything now requires an explicit --all-tables opt-in
  • Backfill correctness: real primary-key column discovery (no more assumed id), quoted identifiers in snapshot SQL, WAL-canonical PK forms so watermark hashes match (BKF-02)
  • Router correctness: cursor floor for blocked message groups, per-partition pending buffers, per-consumer cursor gating (RTR-04)
  • Performance: raw-bytes fan-out passthrough (no per-consumer re-marshal), event-driven dispatch replacing the 10 ms poll loop, batched MongoDB and backfill appends
  • Log hygiene: DSN passwords and raw primary-key values redacted from all logs
v0.2.0May 2026Queue Sinks
  • 5 new output sinks: NATS JetStream, AWS SQS FIFO, Kafka, Google Pub/Sub, RabbitMQ — select with --output nats|sqs|kafka|pubsub|rabbitmq
  • At-least-once delivery — cursor never advances before the broker acknowledges receipt (CHK-01 preserved)
  • Per-key ordering end-to-end: MessageGroupId (SQS), record key (Kafka), ordering key (Pub/Sub), subject routing (NATS)
  • Per-table topic/queue routing via Go template: cdc.{{.Schema}}.{{.Table}} — supported on all five sinks (subject, queue-URL, topic, and routing-key templates)
  • SQS: CA pinning and mTLS (CertFile + KeyFile) wired into AWS SDK HTTP transport; startup validation for incomplete mTLS config
  • Prometheus metrics (queue_publish_total, queue_publish_errors_total, queue_publish_latency_seconds) and /healthz probe for each active sink
  • RabbitMQ: publisher confirms, 64-partition channel pool, exponential-backoff reconnect loop
  • Distributed mode — embedded NATS JetStream replicated event log, 64-partition active/active delivery, epoch fencing
v0.1.0Apr 2026Initial Release
  • Postgres WAL CDC via pgoutput — insert, update, delete, TOAST handling, schema evolution
  • MongoDB Change Streams — BSON normalization, resume tokens, automatic re-snapshot on token expiry
  • Three output modes: stdout NDJSON, SSE with per-consumer cursors and Last-Event-ID, gRPC streaming
  • Consistent backfills — keyset cursors, watermark dedup, crash-resumable snapshot progress
  • High availability — Postgres advisory lock leader election, ~5s failover, shared checkpoint store
  • Optional Rust FFI acceleration for pgoutput decoding and JSON serialization
  • Benchmark suite — Docker Compose harness vs. Debezium, Sequin, PeerDB across 5 scenarios

Your first event in two minutes.

Install kaptanto, point it at your database, and start streaming.