Skip to content

This project is a minimal Go implementation of the outbox pattern for an e‑commerce style engine

Notifications You must be signed in to change notification settings

atharvamhaske/outboxy

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Outboxy – Outbox Pattern Demo (Orders + Dispatcher)

This project is a minimal Go implementation of the outbox pattern for an e‑commerce style engine.
It has two small Go services:

  • orders writes orders and their corresponding outbox records in a single Postgres transaction.
  • dispatcher continuously polls the outbox table and publishes events to Redis pub/sub.

Both services are built as plain Go binaries in this module.

High Level Architecture

Outboxy architecture

Screenshots

Dispatcher worker logs Redis client subscriber
Dispatcher demo Redis client demo

Components

  • Postgres – primary data store for orders and outbox messages.
  • Redis – pub/sub transport; dispatcher publishes orders.created events.
  • Orders service (./orders)
    • Inserts into orders table.
    • Inserts a serialized OrderEvent into outbox table with state = 'pending'.
  • Dispatcher service (./dispatcher)
    • Periodically (every second) selects one pending outbox row with FOR UPDATE SKIP LOCKED.
    • Publishes the message to Redis channel = topic.
    • Marks the outbox row as processed.

Database schema

Example Postgres schema that matches the code:

CREATE EXTENSION IF NOT EXISTS "pgcrypto";

CREATE TABLE orders (
  id UUID PRIMARY KEY,
  product TEXT NOT NULL,
  quantity INT NOT NULL
);

CREATE TABLE outbox (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  topic TEXT NOT NULL,
  message BYTEA NOT NULL,
  state TEXT NOT NULL DEFAULT 'pending',
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  processed_at TIMESTAMPTZ
);

orders/main.go writes to both orders and outbox inside a single transaction.


Environment variables

  • DATABASE_URL (required for both services)
    Example:

    export DATABASE_URL="postgres://user:password@localhost:5432/outboxy?sslmode=disable"
  • REDIS_URL (optional for dispatcher)
    If empty, the dispatcher uses localhost:6379:

    export REDIS_URL="redis://localhost:6379"

Makefile targets

From the project root (/home/atharvamhaske/Projects/outboxy):

  • Build both binaries

    make build
    # or individually
    make build-orders
    make build-dispatcher
  • Run tests (Ginkgo/Gomega based)

    make test
  • Run services (with env vars set)

    # Orders service – creates an order and an outbox row
    make run-orders
    
    # Dispatcher – polls outbox and publishes to Redis
    make run-dispatcher
  • Go module tidy

    make tidy

Running everything locally

  1. Start Postgres and Redis

    • Postgres database outboxy with the schema above.
    • Redis server (default: localhost:6379).
  2. Set environment variables

    export DATABASE_URL="postgres://user:password@localhost:5432/outboxy?sslmode=disable"
    export REDIS_URL="redis://localhost:6379"
  3. Run dispatcher

    make run-dispatcher
  4. Subscribe to Redis channel to see events

    redis-cli
    SUBSCRIBE orders.created
  5. Trigger an order + outbox entry

    make run-orders
  6. Observe

    • Dispatcher logs: publishing + marking outbox rows as processed.
    • redis-cli subscriber: receives orders.created JSON payloads.
    • DB:
      • orders contains the new order.
      • outbox row moves from pending to processed.

Docker / Docker Compose

You can also run the whole example using Docker.

Prerequisites

  • Docker
  • Docker Compose (or docker compose with recent Docker)

Start the stack

From the project root:

docker compose up --build

This starts:

  • postgres with database outboxy
  • redis
  • dispatcher service polling the outbox table and publishing to Redis
  • orders-once which runs once to create a sample order and outbox record

Inspect behaviour

  • View logs:

    docker compose logs -f dispatcher
    docker compose logs -f orders-once
  • Subscribe to the Redis channel from your host:

    redis-cli -h localhost -p 6379
    SUBSCRIBE orders.created

You should see an orders.created event published when orders-once runs, while the dispatcher marks the outbox record as processed.

About

This project is a minimal Go implementation of the outbox pattern for an e‑commerce style engine

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published