A production-grade Go application demonstrating a real-time e-commerce order processing system with:
- Producer API β writes to sharded Postgres + S3 + publishes to Kafka
- Consumer Service β reads from Kafka only (no S3/Postgres access by design)
- Frontend Dashboard β real-time order placement and monitoring
Frontend (index.html)
β
β POST /api/orders
βΌ
βββββββββββββββββββ
β Producer API β (Go HTTP Server, :8080)
β (main.go) β
ββββββ¬βββββ¬ββββββββ
β β β
β β β 1. INSERT
β β βΌ
β β βββββββββββββββββββ βββββββββββββββββββ
β β β Postgres Shard1 β β Postgres Shard2 β
β β β Users A-M :5432 β β Users N-Z :5433 β
β β βββββββββββββββββββ βββββββββββββββββββ
β β
β β 2. PUT (receipt .txt)
β βΌ
β ββββββββββββββββββββββββ
β β S3 (LocalStack) β
β β bucket:order-receiptsβ
β β port :4566 β
β ββββββββββββββββββββββββ
β
β 3. PUBLISH (order.created event)
βΌ
βββββββββββββββββββ CONSUME βββββββββββββββββββ
β Kafka β βββββββββββββββΊ β Consumer β
β topic: orders β β (Go Service) β
β port: :9092 β β Kafka only β
βββββββββββββββββββ β β No S3/Postgresβ
βββββββββββββββββββ
Orders are sharded by the first letter of user_id:
- Shard 1 (port 5432): Users whose ID starts with AβM
- Shard 2 (port 5433): Users whose ID starts with NβZ
orderflow/
βββ docker-compose.yml # All services orchestration
βββ frontend/
β βββ index.html # Dashboard UI
βββ producer/ # Producer API (Go)
β βββ main.go # Entry point, HTTP server
β βββ Dockerfile
β βββ go.mod
β βββ config/
β β βββ config.go # ENV-based config
β βββ models/
β β βββ order.go # Order structs + Kafka event
β βββ handlers/
β β βββ order.go # HTTP handlers (create, list)
β βββ kafka/
β β βββ producer.go # Kafka producer client
β βββ storage/
β βββ postgres.go # Sharded Postgres (shard1 + shard2)
β βββ s3.go # S3 receipt upload
βββ consumer/ # Consumer Service (Go)
β βββ main.go # Kafka consumer loop
β βββ Dockerfile
β βββ go.mod
β βββ config/
β β βββ config.go
β βββ handlers/
β βββ processor.go # Event processor (Kafka only, no S3/PG)
βββ scripts/
βββ init_shard1.sql # Postgres schema for shard 1
βββ init_shard2.sql # Postgres schema for shard 2
βββ init_localstack.sh # Creates S3 bucket on startup
- Docker and Docker Compose installed
- Go 1.21+ (only for local dev without Docker)
- librdkafka (only for local dev β
brew install librdkafkaon Mac)
cd orderflowchmod +x scripts/init_localstack.shdocker-compose up --buildWait ~30 seconds for all services to initialize. You'll see:
producer | β Connected to sharded Postgres (shard1: A-M, shard2: N-Z)
producer | β S3 client initialized (bucket: order-receipts)
producer | β Kafka producer connected to kafka:9092
producer | β Producer API listening on :8080
consumer | β Subscribed to topic 'orders' with group 'order-consumer-group'
consumer | β Waiting for messages...
Open frontend/index.html in your browser (just double-click the file), or:
open frontend/index.html # Mac
xdg-open frontend/index.html # Linuxdocker-compose up zookeeper kafka postgres_shard1 postgres_shard2 localstackcd producer
go mod tidy
export PG_SHARD1_DSN="postgres://orderuser:orderpass@localhost:5432/orders_shard1?sslmode=disable"
export PG_SHARD2_DSN="postgres://orderuser:orderpass@localhost:5433/orders_shard2?sslmode=disable"
export S3_ENDPOINT="http://localhost:4566"
export KAFKA_BROKERS="localhost:9092"
CGO_ENABLED=1 go run main.gocd consumer
go mod tidy
export KAFKA_BROKERS="localhost:9092"
CGO_ENABLED=1 go run main.gocurl http://localhost:8080/healthcurl -X POST http://localhost:8082/api/orders \
-H "Content-Type: application/json" \
-d '{
"user_id": "alice",
"product_name": "Mechanical Keyboard",
"quantity": 2,
"price": 149.99
}'Response:
{
"order": {
"id": "uuid-here",
"user_id": "alice",
"product_name": "Mechanical Keyboard",
"quantity": 2,
"price": 149.99,
"status": "created"
},
"shard": "shard1",
"shard_info": "shard1 (A-M)",
"receipt": "receipts/alice/uuid-here.txt"
}curl http://localhost:8080/api/orderscurl "http://localhost:8080/api/orders?user_id=alice"# This goes to Shard 1 (A-M)
curl -X POST http://localhost:8080/api/orders \
-H "Content-Type: application/json" \
-d '{"user_id":"alice","product_name":"Monitor","quantity":1,"price":399.99}'
# This goes to Shard 2 (N-Z)
curl -X POST http://localhost:8080/api/orders \
-H "Content-Type: application/json" \
-d '{"user_id":"zara","product_name":"Keyboard","quantity":2,"price":99.99}'
# Verify directly in Postgres
docker exec -it orderflow-postgres_shard1-1 psql -U orderuser -d orders_shard1 -c "SELECT id, user_id, product_name FROM orders;"
docker exec -it orderflow-postgres_shard2-1 psql -U orderuser -d orders_shard2 -c "SELECT id, user_id, product_name FROM orders;"aws --endpoint-url=http://localhost:4566 s3 ls s3://order-receipts/receipts/ --recursivedocker exec -it orderflow-kafka-1 kafka-console-consumer \
--bootstrap-server localhost:9092 \
--topic orders \
--from-beginning| Variable | Default | Description |
|---|---|---|
KAFKA_BROKERS |
localhost:9092 |
Kafka broker addresses |
PG_SHARD1_DSN |
local shard1 | Postgres DSN for shard 1 |
PG_SHARD2_DSN |
local shard2 | Postgres DSN for shard 2 |
S3_ENDPOINT |
http://localhost:4566 |
S3/LocalStack endpoint |
S3_BUCKET |
order-receipts |
S3 bucket name |
PORT |
8080 |
HTTP server port |
| Variable | Default | Description |
|---|---|---|
KAFKA_BROKERS |
localhost:9092 |
Kafka broker addresses |
KAFKA_GROUP_ID |
order-consumer-group |
Consumer group ID |
KAFKA_TOPIC |
orders |
Topic to consume |
docker-compose down -v