SimpleBank
SWAGGER UI

Auto-generated OpenAPI docs served at /swagger/
WHAT IT DOES
SimpleBank is a production-grade banking backend API built with Go. It handles core banking operations through a dual-protocol server that serves both gRPC and HTTP/JSON from a single service definition. The system includes user authentication, account management with multi-currency support, deadlock-free money transfers, and an async email verification pipeline powered by Redis.
- Account Management — Create and manage bank accounts with multi-currency support (USD, EUR, CAD)
- Money Transfers — Transfer funds between accounts with PostgreSQL transaction isolation (deadlock-free)
- User Authentication — PASETO token-based auth with access/refresh token rotation and session tracking
- Email Verification — Async email verification workflow via Redis task queue with retry logic
- Role-Based Access Control — depositor and banker roles with per-endpoint authorization
- Dual Protocol API — Single service serves both gRPC (binary) and HTTP/JSON via gRPC-Gateway
WHY I BUILT IT
I wanted hands-on experience with production backend patterns that go beyond simple CRUD. This project covers gRPC + HTTP dual serving (common in microservice architectures), async task processing with Redis-backed job queues, database transaction patterns with deadlock prevention, and token-based auth with PASETO. It also gave me practice with type-safe SQL via sqlc and graceful shutdown orchestration using Go's errgroup.
TECH STACK
ARCHITECTURE
Request flow — Client → Auth Middleware → Handlers → Store/Redis → PostgreSQL
KEY CHALLENGES
Dual Protocol Serving (gRPC + HTTP)
A single service definition in Protocol Buffers serves both gRPC and HTTP/JSON simultaneously. The HTTP gateway translates JSON requests into gRPC calls, sharing all handler logic without duplication.
Deadlock-Free Money Transfers
The TransferTx implementation orders account locks by ID to prevent deadlocks when concurrent transfers occur between the same pair of accounts. This ensures safe parallel execution without serializing all transfers.
Transaction Composition with Callbacks
Database transactions use a callback pattern that allows composing multiple operations atomically. For example, CreateUserTx creates a user record AND queues an email verification task within the same transaction boundary.
Async Email Verification Pipeline
User registration triggers an async task via Redis/Asynq. The worker generates a secret code, stores it with a 15-minute TTL, and sends a verification email. Priority queues (critical: 10 workers, default: 5) ensure throughput.
Graceful Shutdown Orchestration
Uses Go's errgroup to manage three concurrent services (gRPC server, HTTP gateway, task processor). On SIGTERM/SIGINT, each component shuts down cleanly — gRPC finishes in-flight RPCs, HTTP drains connections, and the worker completes running tasks.
RBAC at the Handler Level
Authorization is enforced per-RPC with role lists. For example, UpdateUser allows both the banker role (can update any user) and the user themselves (can only update their own profile).
HOW TO RUN
git clone https://github.com/moolair/simplebank-golang-backend.git
cd simplebank-golang-backend
docker compose up --buildStarts PostgreSQL, Redis, and the API server. Migrations run automatically on startup. HTTP Gateway at :8080, gRPC at :9090, Swagger UI at /swagger/.
API ENDPOINTS
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /v1/create_user | No | Register a new user |
| POST | /v1/login_user | No | Login and get tokens |
| PATCH | /v1/update_user | Yes | Update user profile |
| GET | /v1/verify_email | No | Verify email with code |
FUTURE IMPROVEMENTS
- Real-time notifications via WebSocket for live transaction alerts
- CI/CD pipeline with GitHub Actions for automated testing and Docker publishing
- Helm charts with ArgoCD for GitOps-based deployment on EKS
- Paginated transaction history API with filtering and search