rinha2-back-end-go

Challenge

Rinha de Backend 2024/Q1

Rinha de Backend is a Brazilian backend programming challenge. The 2024/Q1 edition models a tiny financial API: five predefined clients start with credit limits and zero balances, and the service must accept concurrent credits, debits, and statement reads under a strict container resource cap.

Required API contract

Endpoint Method Expected behavior Current implementation note
/clientes/{id}/transacoes POST Submit a debit (d) or credit (c) transaction for clients 1 through 5. Implemented in postTransacaoHandler; returns id, limite, and updated saldo.
/clientes/{id}/extrato GET Return current balance, credit limit, statement timestamp, and recent transactions. Implemented in getExtratoHandler; returns saldo and up to 10 ultimas_transacoes. Current transaction rows serialize valor, tipo, and descricao; RealizadoEm is stored/selected in SQL but not exposed by the Go DTO.

The repository also exposes GET /healthz for compose/CI health checks; it is not part of the original banking contract.

Current response shapes

POST /clientes/{id}/transacoes returns:

{
  "id": 1,
  "limite": 100000,
  "saldo": 1000
}

GET /clientes/{id}/extrato returns:

{
  "saldo": {
    "total": 1000,
    "limite": 100000,
    "data_extrato": "2026-05-29T22:00:00Z"
  },
  "ultimas_transacoes": [
    {
      "valor": 1000,
      "tipo": "c",
      "descricao": "deposito"
    }
  ]
}

See Source Audit for the complete status-code matrix and edge cases.

Seeded clients

Client Limit
1 100000
2 80000
3 1000000
4 10000000
5 500000

The same IDs and limits appear in both the Go clientes map and the SQL seed data.

Validation rules

Current validation is split between Go and PostgreSQL:

  • Non-integer client IDs return 400 from the Go handlers.
  • Client IDs outside 1–5 return 404 before the database call.
  • Invalid JSON transaction bodies return 400.
  • tipo must be exactly debit (d) or credit (c).
  • descricao must be non-empty and at most 10 characters.
  • valor must be greater than zero.
  • Debits cannot push the balance below -Limite; the current stored procedure refuses the mutation and returns the existing balance, so the Go handler responds with the unchanged balance unless the database call itself fails.
  • Invalid transaction fields return 422.

Resource constraints

The official stack budget is intentionally tight:

Total CPU1.5

Shared across API, NGINX, and PostgreSQL.

Total RAM550MB

Shared across all challenge-counted containers.

Workloadk6

Concurrent transactions, validations, and statement queries.

Why this implementation is interesting

The repository explores a compact Go approach: a small HTTP layer, a simple NGINX fan-out, and PostgreSQL stored procedures for the hot transaction path. The goal is not to build a feature-complete banking system; it is to study performance trade-offs under a fixed resource envelope.

Source specification

Full specification: github.com/zanfranceschi/rinha-de-backend-2024-q1