Relay Engine is a production-inspired email relay service written in Go.
The project is designed as a learning exercise in building backend infrastructure from the ground up while following the architectural principles used by companies such as Resend, Stripe, and Moniepoint.
Rather than focusing on sending emails immediately, the project emphasizes the infrastructure required to operate a reliable, scalable, and observable message relay
- Build a production-quality Go service.
- Learn idiomatic Go architecture.
- Practice dependency injection and clean layering.
- Build a concurrent worker-based relay engine.
- Explore distributed systems concepts through incremental implementation.
The service is implemented with:
Ginfor HTTP routingpgxfor PostgreSQL connection poolingZapfor structured logginggithub.com/google/uuidfor email IDs
The current implementation includes:
GET /ping- returnspongfor liveness checksGET /test-db- inserts a sample email record into PostgreSQL and returns the created ID
Email data is persisted into the emails table with fields such as sender, recipient, subject, text, HTML, status, and created timestamp.
cmd/api/main.go- application entrypointinternal/config- environment configuration loaderinternal/database- PostgreSQL connection pool implementationinternal/repository- email repository with save and lookup functionsinternal/models- email domain modelinternal/router- Gin router and middleware setupinternal/middleware- request logging and recovery middlewaremigrations- SQL migration files for the database schemadocker-compose.yml- local PostgreSQL service definition
- Go 1.25
- PostgreSQL 16 (via Docker Compose or local install)
migrateCLI if you want to run migrations from the included Makefile targets
The service loads configuration from environment variables. The following variables are used:
APP_NAME- application nameAPP_ENV- application environment (development, production, etc.)PORT- HTTP port for the APIDB_HOST- PostgreSQL host (not used directly by the current code, but available in config)DB_PORT- PostgreSQL port (not used directly by the current code, but available in config)DB_USER- PostgreSQL user (not used directly by the current code, but available in config)DB_PASSWORD- PostgreSQL password (not used directly by the current code, but available in config)DB_NAME- PostgreSQL database name (not used directly by the current code, but available in config)DATABASE_URL- PostgreSQL connection URL used by the service
Example DATABASE_URL:
postgres://postgres:password@localhost:5432/relay?sslmode=disable- Start PostgreSQL with Docker Compose:
docker compose up -d- Create the database schema:
make migrate-up- Start the API:
make run- Verify the service:
curl http://localhost:8080/pingYou may need to export PORT and DATABASE_URL before running the service if they are not already set:
export PORT=8080
export DATABASE_URL="postgres://postgres:password@localhost:5432/relay?sslmode=disable"Then run:
go run cmd/api/main.goThe provided docker-compose.yml starts a PostgreSQL container with:
- user:
postgres - password:
password - database:
relay - exposed port:
5432
The repository includes a migration to create the emails table:
migrations/000001_create_emails_up.sqlmigrations/000001_create_emails.down.sql
Run migrations with:
make migrate-upRollback the most recent migration with:
make migrate-downGET /ping- health checkGET /test-db- saves a sample email record and returns the generated UUID
make run- runs the service viago run cmd/api/main.gomake test- runs all Go testsmake fmt- formats Go codemake vet- runsgo vetmake lint- runsgolangci-lintmake up- brings up Docker Compose servicesmake down- tears down Docker Compose servicesmake logs- follows Docker Compose logsmake migrate-up- apply migrationsmake migrate-down- rollback the last migration
- The service reads
DATABASE_URLdirectly and uses it to open a PostgreSQL connection pool. - The current
/test-dbendpoint is intended as a temporary verification helper. - The application does not yet expose a full email sending API; it stores email records for relay testing.