rinha2-back-end-go

Architecture

Runtime topology

The challenge path is deliberately small: two Go API instances sit behind NGINX, and both API containers share one PostgreSQL database. The root compose file also includes observability and k6 services for development, but those services are outside the official resource budget.

[client / k6] ──▶ [nginx :9999 · least_conn]
                       ├──▶ [webapi1-go :8080]
                       └──▶ [webapi2-go :8080]
                                  │
                                  ▼
                         [postgresql :5432]
                                  │
                                  ├──▶ InsertTransacao(...)
                                  └──▶ GetSaldoClienteById(...)

Challenge-counted services

ServiceRoleCPURAMSource
webapi1-goGo 1.25.0 API instance using chi/v5 and pgx/v50.4100MBdocker-compose.yml, prod/docker-compose.yml
webapi2-goSecond identical API instance0.4100MBdocker-compose.yml, prod/docker-compose.yml
nginxReverse proxy and load balancer using least_conn0.220MBnginx.conf, compose files
dbPostgreSQL with stored procedures0.5330MBcompose files, SQL dump

Total counted envelope: 1.5 CPU and 550MB RAM.

Development and test services

ServicePurposeCounted in challenge budget?
k6Runs the external stress-test suite (MODE=dev in root compose, MODE=prod in prod/)No
postgres-exporterExposes PostgreSQL metricsNo
prometheusStores local metricsNo
grafanaLocal dashboardsNo
influxdbOptional k6 time-series output in development modeNo

HTTP layer

src/WebApi/main.go creates a chi router and exposes three routes:

MethodRouteHandler
GET/healthzhealthzHandler returns Healthy.
GET/clientes/{id}/extratogetExtratoHandler validates the ID and calls GetSaldoClienteById($1).
POST/clientes/{id}/transacoespostTransacaoHandler validates JSON and calls InsertTransacao($1, $2, $3, $4).

The HTTP server listens on :8080, uses a 5-second read timeout and a 10-second write timeout, and each database operation runs with a 5-second request-scoped context timeout.

Database strategy

Business rules run in PostgreSQL stored procedures so balance updates and validation stay close to the data. The schema uses UNLOGGED Clientes and Transacoes tables and an index on (ClienteId, Id DESC) for recent statement retrieval.

Benchmark-oriented PostgreSQL flags configured in both compose files:

  • synchronous_commit=0: do not wait for WAL flush on each commit.
  • fsync=0: skip forced syncs during the benchmark run.
  • full_page_writes=0: reduce write amplification.
  • checkpoint_timeout=600 and max_wal_size=4096: reduce checkpoint pressure during runs.

These settings are useful for understanding the contest trade-off; they are not general production-banking defaults.

Build images

src/WebApi/Dockerfile currently builds with golang:1.25-alpine3.21 and copies the binary into an alpine:3.23 runtime image. CI publishes GHCR images from that Dockerfile.