How blnkfinance/blnk works
1. What this repository is
- Blnk is a Go-based financial ledger system, not just a library: it exposes an HTTP API, persists ledger state, and runs background workers for transaction processing, reconciliation, search indexing, and webhooks.
- The core business model is double-entry accounting with accounts, balances, ledgers, identities, API keys, transactions, and lineage/audit records.
2. Top-level runtime shape
- The main executable paths live under cmd/: server.go starts the API server, workers.go starts async processors, migrate.go applies schema changes, and verify_chain.go checks integrity.
- This is effectively a multi-process Go service: one HTTP-facing component and one or more worker components sharing the same database and queue infrastructure.
3. HTTP API boundary
- The api/ package is the external contract surface. It contains handlers for accounts, balances, ledgers, transactions, identities, API keys, reconciliation, search, metadata, admin functions, and hooks.
- api/middleware/ enforces request auth, scope checks, metrics/security concerns, and request sizing before handlers reach domain logic.
- The API layer maps requests to internal models and database operations, and returns structured API errors from internal/apierror.
4. Domain and business objects
- Root-level files like account.go, balance.go, ledger.go, transaction.go, identity.go, lineage.go, reconciliation.go, webhooks.go, and queue.go represent the core business workflows.
- The model/ and api/model/ directories hold shared domain/schema representations and API DTOs, separating transport shapes from storage-oriented forms.
5. Persistence layer
- database/ is the Postgres-backed repository layer. It contains repository methods and query helpers for accounts, balances, ledgers, identities, API keys, transactions, reconciliation, lineage, and queue state.
- SQL migrations live in sql/, and cmd/migrate.go suggests schema evolution is first-class and bundled with the service.
- The repository pattern is strong here: API and business logic depend on repository interfaces, with tests and mocks under database/mocks/.
6. Transaction processing and ledger integrity
- Transaction flow is more than a single insert: files such as transaction_execution.go, transaction_queue.go, transaction_inflight.go, transaction_bulk.go, transaction_refunds.go, and transaction_rejection.go show multiple lifecycle states.
- lineage_* and chain_worker.go indicate an audit/immutability layer that tracks transaction lineage and likely maintains ordered processing or hash-chain style integrity.
- The system supports inflight transactions, recovery, batch processing, coalescing, scheduled work, and bulk operations, which makes the worker pipeline part of correctness, not just performance.
7. Asynchronous subsystems
- queue.go, queue_recovery.go, lineage_worker.go, and chain_worker.go point to background processing driven by durable queue state.
- internal/notification/ and webhooks.go show outbound event delivery as an async concern.
- The presence of recovery components suggests the system is designed to rehydrate or replay unfinished financial workflows after failure.
8. Search and indexing
- internal/search/ and search.go/api/search_api_test.go show a dedicated search subsystem, with infrastructure/k8s-manifests/typesense-* indicating Typesense as the search backend.
- internal/search/reindex.go implies ledger data is indexed asynchronously rather than queried directly from Postgres for search-heavy use cases.
9. Identity and tokenization
- Identity management is a first-class subsystem: identities are stored, queried, and linked to balances/transactions.
- internal/tokenization/ suggests PII tokenization is built into the platform, likely to support safer handling of sensitive identity data without exposing raw values broadly through the API or search layers.
10. Reconciliation
- reconciliation.go, database/reconciliation.go, and reconciliation-focused tests show a subsystem for matching internal ledger records against external statements or provider feeds.
- This is a separate domain workflow from transaction posting: it consumes ledger data and matching rules to produce reconciliation results and status.
11. Infrastructure and external dependencies
- The Kubernetes manifests in infrastructure/k8s-manifests/ define separate deployments for server, worker, Postgres, Redis, Typesense, Prometheus, and Jaeger.
- This makes the intended production topology explicit: Postgres is the system of record, Redis supports queue/cache behavior, Typesense supports search, Prometheus handles metrics, and Jaeger handles tracing.
- docker-compose.yaml and docker-compose.dev.yaml support local stack bring-up with the same service boundaries.
12. Observability and operational tooling
- internal/metrics/, internal/traces/, and docs/metrics.md show built-in metrics and OpenTelemetry tracing support.
- internal/monitoringexporter/ suggests logs/telemetry may be exported with redaction, which matters for financial data safety.
- Tests around logging, metrics security, request size, and tracing indicate operational behavior is part of the contract.
13. Request/data flow summary
- External client request enters api/ → middleware authenticates/authorizes and validates → handlers invoke domain logic → domain uses database/ repositories → Postgres persists the authoritative state.
- For workflows that must continue after the request, work is enqueued or recovered by workers → workers update lineage/chain, dispatch notifications/webhooks, and trigger search reindexing or reconciliation.
- The main architectural boundary is therefore synchronous API handling versus asynchronous ledger-processing and delivery pipelines.
14. How to draw the architecture
- Model the system as a Go monolith split into: API edge, domain services, repository layer, and async workers.
- Show Postgres as the primary datastore, Redis as queue/coordination support, Typesense as search, and external observability services as sidecars/infra dependencies.
- Treat ledger integrity/lineage, reconciliation, and webhook delivery as distinct internal workflows rather than simple CRUD endpoints.
Main entry points: api.go API · workers.go Workers · transaction_execution.go Transactions · repository.go Repository
Components 26
Runtime
Executable entrypoints and process roles
API Edge
HTTP boundary and request handling
- API · External request surface for accounts, balances, ledgers, transactions, identities, search, reconciliation, hooks, and admin
api/api.go - Middleware · Authentication, scopes, sizing, and metrics/security checks
api/middleware/middleware.go - DTOs · Transport models used by the HTTP layer
api/model/model.go
Domain
Ledger business workflows and models
- Accounts · Accounts, balances, ledgers, identities, API keys, and metadata
account.go - Transactions · Transaction execution, bulk processing, inflight handling, refunds, rejection, and batching
transaction_execution.go - Lineage · Immutability, ordering, and audit lineage for ledger events
lineage.go - Reconciliation · Matches internal ledger records against external statements or feeds
reconciliation.go - Search · Search and reindex orchestration for ledger data
search.go - Webhooks · Outbound event delivery and webhook processing
webhooks.go
Persistence
Postgres repositories and schema
- Repository · Repository interfaces and query helpers for ledger entities and workflows
database/repository.go - Txn Store · Queries and state for transaction queues, inflight state, recovery, grouping, and refunds
database/transaction.go - Lineage Store · Persistence for lineage, chain, and outbox records
database/lineage.go - Recon Store · Persistence for reconciliation jobs and results
database/reconciliation.go
Async Workflows
Background processing and outbound delivery
- Queue · Durable queue state, enqueue, and recovery
queue.go - Chain Worker · Background integrity and chain maintenance
chain_worker.go - Lineage Worker · Background lineage processing and recovery
lineage_worker.go - Hook Worker · Async webhook notification dispatch
internal/hooks/worker.go - Reindexer · Async search indexing and reindexing
internal/search/reindex.go - Notifier · Notification fanout used by webhook and async workflows
internal/notification/notification.go
Infra
Supporting services and deployment manifests
- Postgres · Primary database for ledger state and workflow state
infrastructure/k8s-manifests/postgres-statefulset.yaml - Redis · Queue and coordination support
infrastructure/k8s-manifests/redis-deployment.yaml - Typesense · Dedicated search backend for indexed query use cases
infrastructure/k8s-manifests/typesense-deployment.yaml - Observability · Prometheus, Jaeger, and telemetry export support
infrastructure/k8s-manifests/prometheus-deployment.yaml
Connections 31
- Server → API: serves · HTTP server exposes the API boundary
- Server → Repository: uses · Server handlers depend on repositories and DB access
- Workers → Queue: consumes · Workers process durable queue state
- Workers → Chain Worker: runs · Starts integrity maintenance worker
- Workers → Lineage Worker: runs · Starts lineage processing worker
- Workers → Hook Worker: runs · Starts webhook delivery worker
- Workers → Reindexer: runs · Starts search reindexing worker
- Migrate → Postgres: migrates · Applies schema changes to Postgres
- API → Middleware: guards · Requests pass through auth and policy middleware
- API → DTOs: maps to · Handlers translate between HTTP DTOs and domain shapes
- API → Accounts: calls · Account, balance, ledger, identity, and key operations
- API → Transactions: calls · Transaction posting and query operations
- API → Reconciliation: calls · Reconciliation endpoints drive matching workflows
- API → Search: calls · Search endpoints query or trigger indexing flows
- API → Webhooks: calls · Hook/admin endpoints manage outbound delivery
- Accounts → Repository: persists via · Domain state is stored through repository interfaces
- Transactions → Txn Store: persists via · Posting engine reads and writes transaction state
- Transactions → Queue: enqueues · Long-running or deferred transaction work is queued
- Transactions → Lineage: records · Transaction execution feeds audit lineage
- Lineage → Lineage Store: persists via · Lineage and chain records are stored durably
- Reconciliation → Recon Store: persists via · Reconciliation jobs and results are stored durably
- Search → Reindexer: triggers · Indexing is handled asynchronously
- Webhooks → Hook Worker: dispatches · Webhook delivery is delegated to async workers
- Chain Worker → Lineage Store: reads/writes · Integrity worker maintains chain and audit records
- Lineage Worker → Lineage Store: reads/writes · Lineage worker processes audit/outbox state
- Hook Worker → Notifier: uses · Webhook delivery relies on notification fanout
- Reindexer → Typesense: indexes to · Search documents are pushed into Typesense
- Repository → Postgres: backed by · Repositories use Postgres as system of record
- Queue → Redis: backed by · Queue/coordination state uses Redis support
- API → Observability: emits · API and middleware feed metrics and tracing
- Workers → Observability: emits · Workers are instrumented for metrics and tracing