Skip to content

PaulBabatuyi/double-entry-bank-Go

Repository files navigation

Double-Entry Bank Ledger in Go

CI Docker CodeQL Go Report Card License: MIT

Production-focused Go backend that models bank-style money movement using strict double-entry accounting.

It demonstrates:

  • Atomic transactions with PostgreSQL
  • Concurrency safety with serializable isolation + retry
  • Ledger-based reconciliation
  • JWT auth + account-level authorization
  • API docs, health checks, and Dockerized deployment

The frontend is intentionally minimal — Next.js Typescript, — so the focus stays on the Go backend. See the frontend repo for details.

Live Demo

Dont forget to star and fork this project repo

Article vs README

This README is intentionally concise and implementation-focused.

For the full technical narrative and tutorial, read the FreeCodeCamp article: How to Build a Bank Ledger in Golang with PostgreSQL using Double-Entry Accounting
freecodecamp

Core Ledger Model

Each money movement writes balanced entries into the entries table:

  • deposit: credit user account, debit settlement account
  • withdrawal: debit user account, credit settlement account
  • transfer: debit source account, credit destination account

Key constraints and behaviors implemented in code:

  • single-sided entry rows (debit xor credit)
  • account row locking (FOR UPDATE) during balance-changing operations
  • serializable transactions with automatic retry on SQLSTATE 40001
  • reconciliation query computes SUM(credit) - SUM(debit) as source of truth Demo

Tech Stack

  • Go 1.24+
  • Router: go-chi/chi
  • Database: PostgreSQL 16
  • Query layer: sqlc
  • Auth: JWT (go-chi/jwtauth)
  • Logging: zerolog
  • API docs: swaggo + http-swagger
  • Testing: Go test + testify + race detector
  • Runtime: Docker + docker-compose

API Endpoints

Public:

  • POST /register
  • POST /login
  • GET /health
  • GET /swagger/index.html

Protected (Bearer token required):

  • POST /accounts
  • GET /accounts
  • GET /accounts/{id}
  • POST /accounts/{id}/deposit
  • POST /accounts/{id}/withdraw
  • POST /transfers
  • GET /accounts/{id}/entries
  • GET /accounts/{id}/reconcile
  • GET /transactions/{id} Backend API Endpoint; Swagger Documentation

Project Structure

.
├── cmd/
│   └── main.go
├── internal/
│   ├── api/
│   ├── db/
│   └── service/
├── postgres/
│   ├── migrations/
│   ├── queries/
│   └── sqlc/
├── docs/
├── docker-compose.yml
├── docker-entrypoint
├── Dockerfile
├── Makefile
└── README.md

Local Development

Prerequisites

  • Go 1.24+
  • Docker + docker compose
  • migrate CLI
  • sqlc CLI
  • swag CLI (only needed when regenerating docs)

Install tools:

go install github.com/golang-migrate/migrate/v4/cmd/migrate@latest
go install github.com/sqlc-dev/sqlc/cmd/sqlc@latest
go install github.com/swaggo/swag/cmd/swag@latest

Run Locally

git clone https://github.com/PaulBabatuyi/double-entry-bank-Go.git
cd double-entry-bank-Go
cp .env.example .env
# Set JWT_SECRET to at least 32 characters: openssl rand -base64 32

make postgres
make migrate-up
make sqlc
make server

Open:

Testing

Recommended (requires Docker running):

make postgres
make test

With coverage report:

make coverage

Full CI-style run including migrations:

make ci-test

Environment used by tests:

  • TEST_DB_URL (defaults to postgresql://root:secret@localhost:5433/simple_ledger?sslmode=disable)

Make Targets

make postgres       # Start PostgreSQL container
make migrate-up     # Apply migrations
make migrate-down   # Rollback last migration
make sqlc           # Regenerate sqlc query code
make server         # Run the API server
make test           # Run tests with race detector
make coverage       # Generate coverage report
make lint           # Run golangci-lint
make ci-test        # Full test run including migrations
make docker-build   # Build Docker image locally
make docker-up      # Start full stack with Docker Compose
make docker-down    # Stop Docker Compose services

Deployment

Render deployment instructions are in DEPLOYMENT.md.

The container serves the backend API only. The frontend is deployed separately.

Why This Project Exists

This repository is a practical fintech-backend demonstration covering:

  • correctness under concurrency
  • auditable money movement
  • clear API boundaries
  • production-minded deployment shape

If you are a recruiter or reviewer, start with this README and the Swagger UI. For the full technical narrative, read the FreeCodeCamp article linked above.

About

Double-Entry Bank Ledger in Go is a production-focused backend that demonstrates how to correctly handle money movements using strict double-entry accounting with PostgreSQL, Atomic transactions, concurrency-safe operations (serializable isolation + automatic retries), row-level locking, and full ledger reconciliation patterns used by fintech syste

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors