04
Go-Bankify

Go-Bankify

Built a Golang backend for account management and transactional money transfers with PostgreSQL, sqlc, and REST APIs.

PeriodFeb 2024 - Apr 2024
StackGolang, Docker
Status Shipped

The Problem

Banking systems are the canonical example of software that must be correct. Account balances can't go negative (unless intended), transfers must be atomic, and concurrent access must not corrupt state. Building one from scratch forces you to take correctness seriously.

Architecture

Go-Bankify is a REST API built with Go's net/http (or a lightweight router). PostgreSQL handles persistence with proper transaction isolation. JWT tokens manage authentication.

The core operations are: create account, deposit, withdraw, transfer between accounts, and query balance. Each operation is wrapped in a database transaction.

Key Decisions

Database transactions for everything. A transfer is two operations (debit + credit) that must succeed or fail together. PostgreSQL's transaction isolation levels handle this correctly.

Docker Compose for development. PostgreSQL in a container means zero setup: docker compose up and you have a working database.

JWT auth keeps the API stateless. Tokens carry user identity and expire after a configurable window. No session storage needed.

What I Learned

The hardest problem was handling concurrent transfers. Two transfers from the same account can race each other. If both read the balance before either writes, you can overdraw. Pessimistic locking (SELECT FOR UPDATE) solved this, but it's a reminder that "it works in testing" and "it works under concurrency" are very different things.