Blueprints
Go — Blueprint
REST API backend with Go 1.23, Gin, and PostgreSQL
REST API backend built with Go 1.23, Gin, and PostgreSQL. Intended as a starting point for Kubernetes-deployed services: one table, one API endpoint, Swagger UI, full Docker support out of the box.
Tech stack:
| Layer | Technology |
|---|---|
| Language | Go 1.23 |
| HTTP framework | Gin |
| Database driver | pgx/v5 (pgxpool) |
| Migrations | golang-migrate (embedded) |
| API docs | swaggo/swag + gin-swagger |
The application starts on port 8080 (overridable via PORT). Opening / redirects to the Swagger UI at /swagger/index.html.
Project Structure
├── main.go # Entry point: Gin router, migrations, PORT env var
├── db.go # Connection string builder + pgxpool setup
├── migrate.go # golang-migrate with embedded migrations/
├── handler.go # SpaceTarget struct, infoHandler, listTargets
├── migrations/
│ ├── 000001_init.up.sql # Creates space_target table + seed data
│ └── 000001_init.down.sql # Drops the table
└── docs/ # Auto-generated by swag init — do not edit manuallyKey design decisions:
db.gobuilds the connection string fromDATABASE_URL(if set) or from individualDB_*variables, then creates apgxpool.Pool— a connection pool managed by pgx directly, without an ORM.migrate.goembeds themigrations/directory at compile time using//go:embed. On startup,main.goruns migrations before the server accepts requests.- Swagger docs are generated from Go annotations in
handler.gobyswag init. Thedocs/directory is committed to the repo so the binary can be built without theswagtool at runtime. When adding new endpoints, regenerate withswag init. - The Dockerfile runs
swag initin the build stage so the final image is always up to date. - To add a new endpoint: add a handler function with swag annotations in
handler.go(or a new file), register the route inmain.go, and runswag init.
Environment Variables
The application runs on port 8080 by default.
| Variable | Required | Default | Description |
|---|---|---|---|
PORT | no | 8080 | HTTP port |
Database connection is configured via one of two approaches:
Option A — Single connection URL (recommended for managed services)
| Variable | Required | Example |
|---|---|---|
DATABASE_URL | yes | postgres://user:pass@host:5432/dbname?sslmode=require |
Option B — Individual variables
| Variable | Required | Default | Description |
|---|---|---|---|
DB_HOST | no | localhost | Database host |
DB_PORT | no | 5432 | Database port |
DB_NAME | no | spacedb | Database name |
DB_USER | no | postgres | Database user |
DB_PASSWORD | no | postgres | Database password |
DB_SSL_MODE | no | disable | SSL mode, e.g. require or disable |
DATABASE_URL takes precedence. If it is set, the individual DB_* variables are ignored.
Running Locally
With Docker Compose
docker compose upStarts the application together with a PostgreSQL instance and sets DATABASE_URL automatically. No additional configuration needed.
Standalone
# install swag once (generates Swagger docs from annotations)
go install github.com/swaggo/swag/cmd/swag@latest
# generate docs and build
swag init
go build -o server .
# run — Option A
DATABASE_URL=postgres://postgres:postgres@localhost:5432/spacedb?sslmode=disable ./server
# run — Option B
DB_HOST=localhost DB_USER=postgres DB_PASSWORD=secret ./server
# or run without building
swag init && DATABASE_URL=postgres://postgres:postgres@localhost:5432/spacedb?sslmode=disable go run .