GoTracker is a small Go service for creating and reading orders with a production-style delivery path:
- PostgreSQL stores the source of truth.
- Redis accelerates
GET /orders/{id}. - Kafka receives order-created events.
- Transactional outbox keeps order writes and event publishing consistent.
- Go
- PostgreSQL
- Redis
- Apache Kafka
- Docker Compose
sqlxgo-redis/v9segmentio/kafka-gogolangci-lintgoose
POST /orderswrites the order to PostgreSQL.GET /orders/{id}checks Redis first, then falls back to PostgreSQL.PUT /orders/{id}updates PostgreSQL and refreshes Redis.
- Order creation writes both
ordersandoutbox_eventsin one transaction. - The relay polls pending outbox rows.
- Kafka producer sends the event to the
orderstopic. - The consumer reads the event and logs it.
gotracker/
├── cmd/
│ ├── api/ # HTTP API entrypoint
│ └── consumer/ # Kafka consumer entrypoint
├── internal/
│ ├── cache/ # Redis cache layer
│ ├── http/ # HTTP handlers
│ ├── order/ # Domain model
│ ├── queue/ # Kafka + outbox relay
│ ├── repository/ # PostgreSQL access
│ └── service/ # Business logic
├── migrations/ # Goose migrations
├── docker-compose.yml # Full local stack for app + dependencies
├── Dockerfile # Multi-stage image build for API and consumer
├── Makefile # Common developer commands
└── .github/workflows/ci.yml # GitHub Actions pipeline
- Start the full stack:
make compose-up- Check containers:
docker compose ps- Check health:
curl -i http://localhost:8080/health-
API is available at
http://localhost:8080. -
Stop the stack when you are done:
make compose-down- Create a local
.envfrom.env.example. - Start only infrastructure:
make compose-up-infra- Install Goose and apply migrations:
go install github.com/pressly/goose/v3/cmd/goose@latest
make migrate- Install
golangci-lintif you want to runmake lintlocally:
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.12.2- Run the API:
make run- In another terminal, run the Kafka consumer:
make run-consumermake help
make build
make image-build
make run
make run-consumer
make test
make lint
make fmt
make migrate
make migrate-status
make migrate-down
make compose-up
make compose-up-infra
make compose-downCreate an order:
curl -i -X POST http://localhost:8080/orders \
-H "Content-Type: application/json" \
-d '{"name":"Петя","address":"ул. Ленина, 1","is_delivered":false}'Get all orders:
curl -i http://localhost:8080/ordersGet one order:
curl -i http://localhost:8080/orders/1Update an order:
curl -i -X PUT http://localhost:8080/orders/1 \
-H "Content-Type: application/json" \
-d '{"name":"Петя","address":"ул. Пушкина, 99","is_delivered":true}'Check application health:
curl -i http://localhost:8080/health- API logs show Redis cache hit, miss, and cache write failures.
GET /healthshows whether PostgreSQL and Redis are currently available.- API logs also show the outbox relay processing loop.
- Consumer logs show created order events received from Kafka.
make compose-upbuilds and starts PostgreSQL, Redis, Kafka, migrator, API, and consumer.- The
migrateservice applies Goose migrations before the API starts. - Local
.envis still useful formake runandmake migrate. - Docker Compose uses internal hostnames such as
postgres,redis, andkafkafor container-to-container communication.
GitHub Actions runs on push and pull request and performs:
make testmake buildgolangci-lint
The workflow file lives in .github/workflows/ci.yml.