Home
Python 3.14 implementation for the Rinha de Backend 2024/Q1 challenge. Manages a fictional bank API with transaction processing and balance statements under strict resource constraints (1.5 CPU, 550MB RAM total across all containers). Built with Flask 3.1, Gunicorn, and psycopg2.
Wiki Pages
| Page | Description |
|---|---|
| Challenge | What is Rinha de Backend 2024/Q1 |
| Architecture | Stack, services, resource constraints |
| Getting Started | Prerequisites and how to run |
| Performance | Results, benchmarks, resource usage |
| CI/CD Pipeline | GitHub Actions workflows |
Key Features
- Python 3.14 with Flask 3.1 for lightweight HTTP routing
- Gunicorn WSGI server for multi-worker concurrency
- psycopg2 for efficient PostgreSQL connectivity
- PostgreSQL stored procedures for server-side business logic
- Consistent throughput under strict resource constraints
Architecture
Tech Stack
| Technology | Version | Purpose |
|---|---|---|
| Python | 3.14 | Language runtime |
| Flask | 3.1.3 | Web framework |
| Gunicorn | 25.3.0 | WSGI HTTP server (4 workers, 2 threads) |
| psycopg2-binary | 2.9.12 | PostgreSQL adapter |
| PostgreSQL | 16.7 | Database with stored procedures |
| NGINX | 1.27 | Reverse proxy / load balancer (least_conn) |
| Docker | - | Containerization (python:3.14-slim base) |
| k6 | - | Load / stress testing |
Overview
NGINX (:9999, least_conn)
├── webapi1-python (:8080, 0.4 CPU, 100MB) — Gunicorn 4w x 2t
├── webapi2-python (:8080, 0.4 CPU, 100MB) — Gunicorn 4w x 2t
└── PostgreSQL (0.5 CPU, 330MB)
├── InsertTransacao() — atomic balance + validation
└── GetSaldoClienteById() — statement with JSONB
Services
| Service | Role | CPU | RAM |
|---|---|---|---|
| webapi1 | Python API instance (Gunicorn 4w x 2t) | 0.4 | 100MB |
| webapi2 | Python API instance (Gunicorn 4w x 2t) | 0.4 | 100MB |
| nginx | Reverse proxy / load balancer (least_conn) | 0.2 | 20MB |
| postgresql | Database with stored procedures | 0.5 | 330MB |
| k6 | Load testing | (not counted) | (not counted) |
| grafana + influxdb | Observability dashboards | (not counted) | (not counted) |
Load Balancing
Nginx uses least_conn strategy to distribute requests across the two API instances.
Database
Business logic is implemented in PostgreSQL stored procedures (InsertTransacao, GetSaldoClienteById). The database uses UNLOGGED tables and is tuned for maximum write performance:
synchronous_commit=0— no wait for WAL flushfsync=0— skip fsync on writesfull_page_writes=0— skip full page writes
Connection Management
The API uses psycopg2 SimpleConnectionPool with 1-10 connections per instance for efficient database access.
Gunicorn Configuration
--workers=4 --threads=2 --worker-class=sync --bind=0.0.0.0:8080 --timeout=30 Challenge
Rinha de Backend 2024/Q1
The Rinha de Backend is a Brazilian backend programming challenge. The 2024/Q1 edition simulates a fictional bank called “Rinha Financeira” that manages up to 5 named clients, each seeded at startup with a credit limit and initial balance.
Endpoints
Three API endpoints are implemented:
| Endpoint | Method | Description |
|---|---|---|
/clientes/{id}/transacoes | POST | Submit a debit or credit transaction for a client (IDs 1-5) |
/clientes/{id}/extrato | GET | Get a client’s current balance, credit limit, and recent transactions |
/healthz | GET | Health check endpoint |
Constraints
The challenge imposes strict resource limits across all containers combined:
- 1.5 CPU total shared across all services
- 550MB RAM total shared across all services
- The system is stress tested using Grafana k6 with concurrent users submitting transactions and querying statements
Source
Full specification: github.com/zanfranceschi/rinha-de-backend-2024-q1
Getting Started
Prerequisites
- Docker with Docker Compose
Clone and Run
git clone https://github.com/jonathanperis/rinha2-back-end-python.git
cd rinha2-back-end-python
docker compose up nginx -d --build
Access
The API is available at http://localhost:9999
Endpoints
| Endpoint | Method | Description |
|---|---|---|
/clientes/{id}/transacoes | POST | Submit debit or credit transaction |
/clientes/{id}/extrato | GET | Get account balance statement |
/healthz | GET | Health check |
Example Requests
Create Transaction
curl -X POST http://localhost:9999/clientes/1/transacoes \
-H "Content-Type: application/json" \
-d '{"valor": 1000, "tipo": "c", "descricao": "deposito"}'
Get Statement
curl http://localhost:9999/clientes/1/extrato
Health Check
curl http://localhost:9999/healthz
Run Stress Tests
docker compose up k6 --build --force-recreate Performance
Resource Constraints
The challenge allows a total of 1.5 CPU and 550MB RAM across all containers.
Actual Usage
| Metric | Limit | Actual | Margin |
|---|---|---|---|
| RAM | 550MB | ~250MB | 60% below limit |
| Response time | - | < 800ms | All requests |
Results
- All requests completed under 800ms
- Total RAM usage of approximately 250MB, which is 60% below the 550MB limit
- Built for learning purposes
Stress Testing
Load tests are run using the shared rinha2-back-end-k6 test suite, which simulates concurrent users performing debits, credits, validations, and statement queries.
Reports are published automatically to GitHub Pages after each main release.
CI/CD Pipeline
Workflows
This repository uses four GitHub Actions workflows:
| Workflow | File | Trigger | Description |
|---|---|---|---|
| Build Check | build-check.yml | Pull requests | Docker build + health check (20 retries) |
| Main Release | main-release.yml | Push to main | Multi-platform Docker push (amd64/arm64) to GHCR + container test + k6 load test |
| CodeQL | codeql.yml | Push to main, PRs, weekly | Security and code quality analysis |
| Deploy | deploy.yml | Push to main | Deploy docs to GitHub Pages via Actions |
build-check.yml
- Trigger: Pull requests
- Steps: Builds the API container with Docker Compose and runs a health check endpoint test (20 retries) to verify the service starts correctly
- Purpose: Catch build failures and regressions before merging
main-release.yml
- Trigger: Push to main branch
- Steps:
- Builds a multi-platform Docker image (linux/amd64, linux/arm64) and pushes to GitHub Container Registry (GHCR)
- Runs a container health check test against the production compose stack
- Runs k6 load tests and commits the stress test report to
docs/reports/
- Purpose: Automated release of production-ready container images with verification
- Image:
ghcr.io/jonathanperis/rinha2-back-end-python:latest
codeql.yml
- Trigger: Push to main, pull requests, weekly schedule
- Steps: Runs GitHub CodeQL analysis for security vulnerabilities and code quality
- Purpose: Continuous security scanning
deploy.yml
- Trigger: Push to main branch
- Steps: Deploys the
docs/directory to GitHub Pages usingactions/deploy-pages - Purpose: Publish documentation and stress test reports to GitHub Pages