outboxer

module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2026 License: MIT

README

Outboxer

Outboxer

CI Go Report Card

Outboxer is a standalone worker application that reads events from a PostgreSQL database and sends them to AWS SQS or GCP Pub/Sub using the outbox pattern. This lets you create events from within your database transactions, making sure that SQS and Pub/Sub see your events in the same order in which they are serialized. Outboxer guarantees at-least-once delivery, ensuring that no event is ever lost.

Outboxer is high throughput, low latency, easy to operate, and integrates nicely with the GCP and AWS platforms. All event properties and options of SQS and Pub/Sub are supported.

Outboxer is best deployed as a Kubernetes component, a GCP Cloud Run service, or an AWS ECS service. It is configurable with environment variables. It is implemented in Go and published as a small Docker image.

ghcr.io/fvdsn/outboxer:latest

Basic Configuration and Usage

In PostgreSQL, you need to create a table with at least an id column and a payload column. The id determines event ordering and idempotency. The payload is passed as-is to the event backend. The table and column names are configurable in Outboxer. Other columns enable routing and backend-specific options for more advanced scenarios — see docs/events.md.

CREATE TABLE events (
    id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    payload text NOT NULL
);

Then configure Outboxer to connect to that table and to the queue or topic of your choice.

resource "google_cloud_run_v2_service" "outboxer" {
  name     = "outboxer"
  location = "europe-west1"

  template {
    scaling {
      min_instance_count = 1
    }

    containers {
      image = "ghcr.io/fvdsn/outboxer:latest"

      args = [
        "--pubsub-enabled",
        "--default-pubsub-topic=projects/my-gcp-project/topics/events",
        "--pg-host=10.0.0.5",
        "--pg-user=outboxer",
        "--pg-password=change-me",
        "--pg-database=app",
      ]

      resources {
        cpu_idle = false
      }
    }
  }
}

Publishing an event is then a matter of inserting a row into the events table. Outboxer sends the event and deletes the row once the send is complete.

INSERT INTO events (payload)
VALUES ('{"type":"user.created","id":"123"}');

Note that the Outboxer must always run as at least one active instance. It continuously polls from a single PostgreSQL connection.

Supported Features

  • GCP Pub/Sub
    • Ordering keys and ordered publishing
    • Custom attributes
    • Multiple topics
    • Default topic
    • Keyless publishing from GCP or AWS via Google external account credentials
  • AWS SQS
    • Standard queues with batch sends
    • FIFO queues and message groups
    • Stable deduplication IDs from event IDs
    • Custom attributes
    • Multiple queues
    • Default queue
    • AWS role assumption
    • Keyless publishing from AWS or GCP via web identity federation
  • Multi instances
    • Split per backend (GCP / AWS)
    • Split per queue / topic
  • Outbox processing
    • At-least-once delivery
    • Ordered processing by event ID
    • Transactional delete after confirmed publish
    • Configurable table and column names
    • Dynamic routing with target and destination
    • Backend-specific event options (ordering keys, attributes, FIFO groups)
    • Optional destination ownership with PUBSUB_DESTINATIONS and SQS_DESTINATIONS
    • Safe multi-instance deployments when split by backend or destination
    • PostgreSQL dead letter queue for poison events
    • Age-based poison handling with MAX_EVENT_AGE_MS
    • Periodic operational statistics logging
    • Graceful shutdown, health endpoint, timeouts, and watchdog

Dead Letter Queue

Events that are permanently unsendable (oversized payloads, malformed options, expired events, and similar content poison) can be routed to a PostgreSQL dead letter table instead of being deleted. Set DLQ_TABLE to enable it. Routing failures and retryable provider errors are never dead-lettered — they stay in the outbox table for a later retry. See docs/dlq.md.

Documentation

  • Events — table schema, routing, and backend-specific options
  • Configuration — full environment variable and flag reference
  • Logging — log catalog, levels, and the periodic statistics fields
  • Dead Letter Queue — poison handling and the DLQ table
  • Authentication — credentials and cross-cloud workload identity
  • Deployment — Cloud Run, GKE, ECS Fargate, and EKS examples

Directories

Path Synopsis
cmd
outboxer command
Package main is the outboxer command-line entry point.
Package main is the outboxer command-line entry point.
internal
outboxer
Package outboxer implements a worker for the transactional outbox pattern: it reads events from a PostgreSQL table and publishes them to Google Pub/Sub or AWS SQS.
Package outboxer implements a worker for the transactional outbox pattern: it reads events from a PostgreSQL table and publishes them to Google Pub/Sub or AWS SQS.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL