Build an order pipeline that is simple, observable, and event-driven.
You send an order once, and the system handles the rest:
- persist order + event atomically
- relay events from Postgres outbox to Kafka
- run fulfillment + recovery workers
- notify customers through WhatsApp (Twilio/Meta) or stdout
This repo is a Go-based order system using:
Ginfor HTTP APIPostgresfor source of truthOutbox patternfor reliable event publishingKafkafor async workflow- workers for fulfillment, recovery, and notifications
- Copy env template:
cp .env.example .env- Start infra:
make infra-up- Run services in separate terminals:
make api
make relay
make worker-fulfillment
make worker-recovery
make worker-notifications- Open tools:
- API health:
http://127.0.0.1:8080/health - Kafka UI (Kafdrop):
http://localhost:19000 - Postgres host port:
5433
- API writes
orders+outboxin one transaction. - Outbox relay picks pending events and publishes to Kafka.
- Fulfillment worker validates and emits:
order.fulfilled, ororder.incomplete, ororder.failed
- Recovery worker retries incomplete orders until max retries, then emits
order.failed. - Notifications worker consumes fulfilled/incomplete/failed events and sends customer updates.
- API entry:
cmd/api/main.go - Router/controller/service:
internal/http/router/router.go,internal/controller/order_controller.go,internal/service/order_service.go - Order write + outbox tx:
internal/repository/order_repository.go - Outbox relay:
cmd/outbox-relay/main.go,internal/outbox/relay.go - Event contract:
internal/ordercontract/contract.go - Fulfillment worker:
cmd/worker-fulfillment/main.go,internal/fulfillment/repository.go - Recovery worker:
cmd/worker-recovery/main.go,internal/recovery/repository.go - Notifications worker:
cmd/worker-notifications/main.go,internal/notification/processor.go - Notification senders:
- Twilio WhatsApp:
internal/notification/whatsapp_twilio_sender.go - Meta WhatsApp:
internal/notification/whatsapp_webhook_sender.go - Stdout:
internal/notification/stdout_sender.go
- Twilio WhatsApp:
- DB schema bootstrap:
internal/database/schema.go
Use stdout:
NOTIFICATION_CHANNEL=stdout
Required basics:
NOTIFICATION_CHANNEL=whatsappNOTIFICATION_RECIPIENT=+<customer_e164_phone>WHATSAPP_PROVIDER=twilioormeta
Twilio (default):
TWILIO_ACCOUNT_SID=<twilio_account_sid>TWILIO_AUTH_TOKEN=<twilio_auth_token>TWILIO_WHATSAPP_FROM=whatsapp:+14155238886
Meta Cloud API:
WHATSAPP_ACCESS_TOKEN=<meta_cloud_api_token>WHATSAPP_PHONE_NUMBER_ID=<meta_phone_number_id>- optional
WHATSAPP_API_VERSION=v21.0
OpenAI message generation (optional):
OPENAI_API_KEY=<openai_api_key>OPENAI_MODEL=gpt-4.1-miniOPENAI_RESPONSES_ENDPOINT=https://api.openai.com/v1/responses
If OpenAI is unavailable, the worker falls back to template messages.
- End-to-end playbook:
docs/end-to-end-verification-playbook.md - Postman collection:
docs/postman/order-system.postman_collection.json - Env template:
.env.example
If you just want a confidence check, run Scenario A/B/C from the playbook and compare final orders + outbox rows.

