# paulbabatuyi/double-entry-bank-go architecture

> Architecture diagram of the GitHub repository paulbabatuyi/double-entry-bank-go, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-08-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/paulbabatuyi/double-entry-bank-go
- Repository: https://github.com/paulbabatuyi/double-entry-bank-go

## Overview

#### Purpose and Entry Point
This is a Go HTTP backend for a bank-style, double-entry ledger. It exposes registration, JWT-authenticated account operations, deposits, withdrawals, transfers, transaction history, and reconciliation. Process startup and dependency wiring originate in `cmd/main.go`; generated OpenAPI artifacts are in `docs/docs.go` and `docs/swagger.yaml`.

#### HTTP API Boundary
The API layer owns routing, request/response DTOs, validation, authentication middleware, authorization checks, and Swagger endpoint exposure. Public routes cover registration, login, health, and documentation; account and ledger routes require Bearer JWTs. Primary paths: `internal/api/handler.go`, `internal/api/middleware.go`, `internal/api/dto.go`.

#### Application and Ledger Domain
`Ledger` is the core business boundary for balance-changing commands. It converts deposits, withdrawals, and transfers into paired debit/credit entry writes, applies account ownership rules, and provides reconciliation/history-facing operations. The service, rather than handlers, owns transaction-level accounting invariants. Primary path: `internal/service/ledger.go`.

#### Transactional Persistence
The store layer bridges domain operations to PostgreSQL and coordinates SQL transactions. Monetary operations use serializable isolation, retry serialization failures (`SQLSTATE 40001`), and lock account rows before changing balances. Generated sqlc code executes typed queries; raw query definitions remain the source for regeneration. Paths: `internal/db/store.go`, `postgres/queries/accounts.sql`, `postgres/sqlc/db.go`.

#### Ledger Data Model and Integrity
PostgreSQL persists users, accounts, and single-sided entry rows. Each entry is debit-or-credit, while every business movement creates balanced opposing entries. Reconciliation derives balance from `SUM(credit) - SUM(debit)`, making entries the accounting source of truth. Schema evolution is migration-driven. Paths: `postgres/migrations/000002_create_accounts_table.up.sql`, `postgres/migrations/000003_create_entries_table.up.sql`, `postgres/queries/entries.sql`.

#### Runtime and External Dependencies
The executable runs on Go 1.24+ with chi routing, JWT middleware, zerolog logging, and Swaggo/http-swagger documentation. PostgreSQL 16 is the required durable datastore. Docker supports local/full-stack execution and container startup; deployment configuration targets Render. Paths: `Dockerfile`, `docker-compose.yml`, `render.yaml`.

#### Primary Control Flow
A protected request passes router/auth middleware, then a handler maps HTTP input to service calls. The ledger service invokes the store’s retrying serializable transaction, which locks involved accounts, updates account state, and writes matching entry records atomically. Results flow back through API mappers/responses. Account history and reconciliation take read paths through typed SQL queries rather than trusting a client-supplied balance.

Main entry points: [`internal/api/handler.go`](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/api/handler.go) (Router and handlers), [`postgres/sqlc/db.go`](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/sqlc/db.go) (Generated typed queries), [`cmd/main.go`](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/cmd/main.go) (Application startup), [`internal/service/ledger.go`](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/service/ledger.go) (Ledger service)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Runtime"]
  node_main{{"Application startup<br/>Go entry point<br/>[main.go]"}}
  node_docker["Container runtime<br/>Docker deployment<br/>[docker-compose.yml]"]
end

subgraph group_api["HTTP API"]
  node_api["Router and handlers<br/>chi HTTP API<br/>[handler.go]"]
  node_middleware["JWT auth middleware<br/>authentication<br/>[middleware.go]"]
  node_dto["Request and response DTOs<br/>API mapping<br/>[dto.go]"]
  node_openapi["Swagger documentation<br/>OpenAPI artifact<br/>[swagger.yaml]"]
end

subgraph group_domain["Ledger Domain"]
  node_ledger{{"Ledger service<br/>accounting domain service<br/>[ledger.go]"}}
end

subgraph group_persistence["PostgreSQL Persistence"]
  node_store["Transactional store<br/>PostgreSQL transaction boundary<br/>[store.go]"]
  node_sqlc["Generated typed queries<br/>sqlc data access<br/>[db.go]"]
  node_account_queries["Account queries<br/>SQL query definitions<br/>[accounts.sql]"]
  node_entry_queries["Entry and reconciliation queries<br/>SQL query definitions<br/>[entries.sql]"]
  node_accounts_schema["Accounts schema migration<br/>database migration"]
  node_entries_schema["Entries schema migration<br/>database migration"]
  node_postgres[("PostgreSQL 16<br/>durable datastore")]
end

node_docker -->|"runs"| node_main
node_main -->|"registers routes"| node_api
node_main -->|"serves docs"| node_openapi
node_api -->|"protected routes"| node_middleware
node_api -->|"maps payloads"| node_dto
node_api -->|"invokes commands and reads"| node_ledger
node_middleware -->|"authenticated request"| node_api
node_ledger -->|"atomic monetary operations"| node_store
node_store -->|"executes typed queries"| node_sqlc
node_sqlc -.->|"generated from"| node_account_queries
node_sqlc -.->|"generated from"| node_entry_queries
node_sqlc -->|"reads and writes"| node_postgres
node_accounts_schema -.->|"creates account tables"| node_postgres
node_entries_schema -.->|"creates entry tables"| node_postgres
node_ledger -.->|"history and reconciliation"| node_entry_queries
node_store -->|"serializable transactions"| node_postgres

click node_main "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/cmd/main.go"
click node_docker "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/docker-compose.yml"
click node_api "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/api/handler.go"
click node_middleware "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/api/middleware.go"
click node_dto "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/api/dto.go"
click node_openapi "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/docs/swagger.yaml"
click node_ledger "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/service/ledger.go"
click node_store "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/db/store.go"
click node_sqlc "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/sqlc/db.go"
click node_account_queries "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/queries/accounts.sql"
click node_entry_queries "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/queries/entries.sql"
click node_accounts_schema "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/migrations/000002_create_accounts_table.up.sql"
click node_entries_schema "https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/migrations/000003_create_entries_table.up.sql"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main,node_docker toneBlue
class node_api,node_middleware,node_dto,node_openapi toneAmber
class node_ledger toneMint
class node_store,node_sqlc,node_account_queries,node_entry_queries,node_accounts_schema,node_entries_schema,node_postgres toneRose
```

## Components

### Runtime

- [Application startup](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/cmd/main.go): Go entry point · Wires dependencies and starts the HTTP server. · `cmd/main.go`
- [Container runtime](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/docker-compose.yml): Docker deployment · Supports local and full-stack startup. · `docker-compose.yml`

### HTTP API

- [Router and handlers](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/api/handler.go): chi HTTP API · Owns public and protected account and ledger endpoints. · `internal/api/handler.go`
- [JWT auth middleware](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/api/middleware.go): authentication · Protects account and ledger routes and applies authorization checks. · `internal/api/middleware.go`
- [Request and response DTOs](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/api/dto.go): API mapping · Validates and maps HTTP payloads. · `internal/api/dto.go`
- [Swagger documentation](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/docs/swagger.yaml): OpenAPI artifact · Published API specification and Swagger endpoint content. · `docs/swagger.yaml`

### Ledger Domain

- [Ledger service](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/service/ledger.go): accounting domain service · Enforces ownership and double-entry invariants for monetary commands. · `internal/service/ledger.go`

### PostgreSQL Persistence

- [Transactional store](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/internal/db/store.go): PostgreSQL transaction boundary · Runs serializable transactions, retries serialization failures, and locks accounts. · `internal/db/store.go`
- [Generated typed queries](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/sqlc/db.go): sqlc data access · Executes typed SQL against PostgreSQL. · `postgres/sqlc/db.go`
- [Account queries](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/queries/accounts.sql): SQL query definitions · `postgres/queries/accounts.sql`
- [Entry and reconciliation queries](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/queries/entries.sql): SQL query definitions · Provides entry history and derived balance reads. · `postgres/queries/entries.sql`
- [Accounts schema migration](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/migrations/000002_create_accounts_table.up.sql): database migration · `postgres/migrations/000002_create_accounts_table.up.sql`
- [Entries schema migration](https://github.com/paulbabatuyi/double-entry-bank-go/blob/main/postgres/migrations/000003_create_entries_table.up.sql): database migration · Defines single-sided debit or credit ledger entries. · `postgres/migrations/000003_create_entries_table.up.sql`
- **PostgreSQL 16**: durable datastore · Persists users, accounts, and accounting entries.

## Connections

- Container runtime → Application startup: runs
- Application startup → Router and handlers: registers routes
- Application startup → Swagger documentation: serves docs
- Router and handlers → JWT auth middleware: protected routes
- Router and handlers → Request and response DTOs: maps payloads
- Router and handlers → Ledger service: invokes commands and reads
- JWT auth middleware → Router and handlers: authenticated request
- Ledger service → Transactional store: atomic monetary operations
- Transactional store → Generated typed queries: executes typed queries
- Generated typed queries → Account queries: generated from
- Generated typed queries → Entry and reconciliation queries: generated from
- Generated typed queries → PostgreSQL 16: reads and writes
- Accounts schema migration → PostgreSQL 16: creates account tables
- Entries schema migration → PostgreSQL 16: creates entry tables
- Ledger service → Entry and reconciliation queries: history and reconciliation
- Transactional store → PostgreSQL 16: serializable transactions
