Self-hosted service
blnkfinance/blnk avatar
blnkfinance/blnk

Blnk and the double-entry ledger behind fintech wallets

Blnk is an open-source ledger & financial core for shipping fintech products fast.

566 stars163 forksGoApache-2.0

At a glance

What is it?
Blnk is an open source double-entry ledger in Go that gives wallet, payment and lending products a set of balance, transaction, reconciliation and identity primitives instead of a hand-rolled balances table, with a Postgres and Redis stack that runs under Docker Compose. The interesting engineering is in the lineage and queue machinery around the core ledger, and the interesting trade is that the open source core sits next to a paid cloud and support offering from the same vendor.
Who is it for?
Blnk is a good fit for a team building a wallet, payment or lending product that needs correct balances, transaction history and reconciliation without writing the accounting core itself, because the double-entry model, the lineage tracking and the reconciliation primitives are the parts that are hard to retrofit later.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem Blnk is aimed at

Blnk is described as an open source, double-entry ledger for teams building fintech products, wallets, banking infrastructure, payment systems, lending products, rewards programs and other transaction-heavy financial applications. The primary language is Go, the licence is Apache 2.0, and the project is not archived with a last push on 2026-10-05.

The framing sentence in the README is the one worth quoting, because it is the argument the whole project rests on: financial products need more than a database table of balances. They need a reliable ledger that can track every movement of value, preserve transaction history, support reconciliation and help teams reason about correctness.

That is a fair characterisation of the failure mode most teams hit. A balances table updated with a SQL UPDATE looks fine until something has to be undone, a transfer is charged back, or two concurrent writes interleave. Double entry is not new, and the project is explicit that it wants teams on those principles from day one, which is the right moment to adopt them.

The listed capabilities follow from that. Teams build on double-entry accounting principles from day one, record transactions across ledgers, balances and identities, monitor balances and historical balance states, handle inflight transactions, scheduled transactions, overdrafts and bulk transaction workflows, reconcile internal ledger records with external statements or provider data, and tokenize and manage identity data linked to balances and transactions.

The audience is therefore a fintech engineering team, not a hobbyist. The repository topics agree, with double-entry, shadow-ledger, multi-currency-ledger, postgres-ledger, reconciliation and wallets among the tags.

The README also lists what teams actually build on it, which is a better guide to scope than the feature list: wallet management, deposits and withdrawals, order exchange, lending, loyalty points, AI billing and escrow applications.

The three capabilities and the file layout that shows them

The core capabilities section names three areas, and the repository root is laid out so that you can see where each one lives.

The ledger itself is described as managing balances and recording transaction workflows, with support for balance monitoring, balance snapshots, historical balances, inflight transactions, scheduling, overdrafts, bulk transactions and other operations needed in production financial systems. The root files match: ledger.go, balance.go, account.go and transaction handling, each with its own test file beside it.

Reconciliation is the second area, and it is described as matching external records, such as bank statements or payment processor exports, against internal ledger records using custom matching rules and reconciliation strategies. The topic list spells it as reconciliaition, with the typo, which is a fair indicator that this is a live area of the project rather than a settled one.

Identity management is the third: creating and managing identities, tokenizing PII, and linking identities to balances and transactions. The file identity.go and identity_test.go cover it.

What is more revealing than the top-level files is the set of names around them. There are lineage.go, lineage_allocation.go, lineage_allocation_metadata.go, lineage_credit.go, lineage_debit.go, lineage_integration_test.go, lineage_outbox.go, lineage_processing.go, lineage_queries.go, lineage_shadow.go and lineage_worker.go. That is a lot of surface for one concept, and the shadow and outbox names point at two specific patterns: tracking how value flows through a chain of ledgers, and an outbox for reliably publishing events.

The other cluster is the queue. queue.go, queue_backpressure.go, queue_recovery.go and their tests, plus chain_worker.go, index_task.go and lineage_worker.go, tell you that a substantial part of this codebase is about asynchronous work: how tasks are enqueued, what happens when the queue backs up, and how in-flight work is recovered after a crash.

The topic list names shadow-ledger explicitly, which is the term for the second, parallel record of balances that a core banking system keeps to compare against the primary one. A project with that in its topics is not a toy balance table.

Running it locally: the Docker Compose topology

The quickest path to understanding the system is the one the README recommends: deploy a sandbox and follow the developer docs. The install documentation lives at docs.blnkfinance.com, and there is a separate cloud sign-up and a support plans page for the managed path.

The compose file is the clearest description of the topology, and it is worth reading before anything else because the number of processes is the first surprise.

There is an init service that runs alpine:3.19 with the repository mounted at /workspace and executes /workspace/blnk-init.sh, with restart set to no. That job prepares the workspace once and exits.

There is a server service, which runs the image jerryenebeli/blnk:0.15.0 by default, overridable through the BLNK_IMAGE variable. Its command is blnk migrate up && blnk start, which is the important detail: the migration runs as part of the service start, so schema changes are applied by the same binary that serves traffic. It depends on init, redis and postgres, publishes port 5001, and mounts a configuration file at /blnk.json.

There is a worker service running the same image but with the entrypoint blnk and the command workers, publishing port 5004. The separation of server and worker is the shape of any system with a task queue, and it matches the queue and worker files in the Go source.

Then there is redis:7.2.4 and postgres:16, with the Postgres port published as 5432 by default and the database name, user and schema all set from the environment.

The environment file lists those defaults as plain variables:

bash
COMPOSE_FILE=docker-compose.yaml
BLNK_PROJECT_NAME=Blnk
TZ=Etc/UTC
POSTGRES_IMAGE=postgres:alpine3.19 #alphine version is smaller in size
POSTGRES_OUTER_PORT=5432
POSTGRES_DB=blnk
POSTGRES_SCHEMA=blnk

The comment on the Postgres image line explains the choice, noting that the alpine version is smaller in size.

Building the image and the Go service inside it

The Dockerfile is a two-stage build and it reveals two things about the project: the language version and the operational assumption about Postgres tooling.

The build stage is golang:1.25-alpine with the working directory set to /go/src/blnk, copies the source in, and builds the binary:

dockerfile
RUN go build -o /blnk ./cmd/*.go

The runtime stage is debian:bullseye-slim, and it is not a scratch image. The reason is the next step: it installs the Postgres client, version 16, by adding the PostgreSQL apt repository, fetching the key, and installing postgresql-client-16. The comment says to install pg_dump version 16.

That is a meaningful choice. pg_dump is a database backup tool, and its presence in the runtime image means the deployed service can take a logical dump of the database, presumably for the backup and reconciliation workflows the project is built around. The cost of that choice is a Debian base layer with apt and its package cache in the image, which is larger and has a larger attack surface than a minimal one.

The binary is then copied from the build stage, made executable, and the default command starts the service:

dockerfile
COPY --from=build-env /blnk /usr/local/bin/blnk

RUN chmod +x /usr/local/bin/blnk

CMD ["blnk", "start"]

The image declares EXPOSE 8080, which is worth noting because it does not match the 5001 that the compose file publishes for the server service. The compose port mapping is what actually determines what is reachable, so the Dockerfile's EXPOSE is informational and the two are not in conflict in practice, but if you deploy the image on its own rather than through compose, the port you expose is the one you configure, not the one in the Dockerfile.

The Go module declares go 1.25.0, so the toolchain floor is recent, and the dependency list shows the shape of the service: gin for HTTP, sql-migrate and lib/pq for Postgres, redis and go-redis for the queue and cache, asynq for the task queue, cobra for the command line, shopspring/decimal for money, logrus for logging, Prometheus and OpenTelemetry for observability, and posthog for product analytics. The presence of test doubles in the same list, go-sqlmock, redismock, miniredis, httpmock and gofakeit, is a hint about how the suite is built.

Money as decimal, and the open source plus vendor split

Two details deserve attention that the README does not dwell on.

The first is shopspring/decimal in the dependency list, with a matching set of queue tests around zero amounts. Floating point is wrong for money, and a ledger that stores balances in float64 will eventually be wrong in a way that is very hard to trace. Using a decimal type is the baseline requirement for a financial ledger, and the presence of a test file named queue_recovery_zero_amount_test.go suggests the author has thought about the specific case of a zero-value transaction moving through recovery, which is the sort of edge case that exposes rounding assumptions.

The second is the commercial structure. Blnk is open source under Apache 2.0 and can be self-hosted and extended for your own stack. Alongside it there is Blnk Cloud with a sign-up flow, and Blnk Support plans for teams integrating Blnk into a production product who want dedicated help from the team.

That arrangement is worth naming plainly rather than treating as a warning. The open source core is genuinely open, and the hosted option is a normal commercial offering from the same vendor, which is a common shape for infrastructure projects where the company needs to fund maintenance. For an evaluation, the questions are: does the part you need stay in the Apache 2.0 core, and what happens to your data and your deploy if the vendor's priorities change. A self-hosted Apache 2.0 codebase answers the second question better than most, since you can fork it and nothing in the licence requires you to keep paying.

The repository also carries a Contributor Covenant 2.1 code of conduct, a CONTRIBUTING.md and a Discord community, and the CI has separate workflows for build and test, Docker publish and lint, with a Prometheus configuration file at the root.

Where Blnk is the wrong choice

Three limits follow from what the repository actually is.

The first is that this is a service, not a library. The top-level entries are account.go, balance.go, ledger.go, identity.go, apikey.go, metadata.go, blnk.go, plus api/, cmd/, config/, database/, infrastructure/, internal/ and model/ directories, and a chain_worker.go at the root. There is no importable package you can add to an existing Go service and call; what you get is a binary with commands, a database schema it manages itself through migrations, a queue it expects to run workers for, and a configuration file it reads. Adopting Blnk means adopting that topology, not just calling a function.

The second is the double-entry requirement. The model is not a general balance store you can use for a single-sided ledger. If your accounting model is one-sided, or if you need a ledger that is not a ledger, this is the wrong shape. Conversely, if you do need double entry, adopting it after launch means migrating a balances table into a proper ledger, which is considerably more work than starting with one.

The third is operational weight. Postgres, Redis, a server, a worker, an init job, migrations, and an outbox and shadow-ledger machinery to understand. The queue recovery and backpressure code is a good sign about the authors' engineering, but it also signals that the system has failure modes worth understanding before you depend on it. And with three tagged releases in the last six weeks, at v0.15.6, the API is still moving.

The honest framing is that Blnk is aimed at a team that has decided to run its own financial core rather than use a third-party ledger API, and that has the Postgres and Redis operational experience that implies. For a team that would rather not operate money infrastructure, the alternative is a hosted ledger provider, and the difference in approach is that Blnk gives you the data model and the control while the hosted option gives you the operations.

Editorial conclusion

Blnk is a good fit for a team building a wallet, payment or lending product that needs correct balances, transaction history and reconciliation without writing the accounting core itself, because the double-entry model, the lineage tracking and the reconciliation primitives are the parts that are hard to retrofit later. It is a poor fit if you want a library you can import into an existing Go service without adopting its server, its database and its queue, since the repository is structured as a deployable service with migrations and background workers rather than a package, and a poor fit if your accounting model is not double entry. Before adopting, read the API reference and the quick start tutorial at docs.blnkfinance.com, and check the deploy topology in docker-compose.yaml, because the server, the worker and the migration step are separate processes with their own configuration.

Frequently asked questions

What is Blnk and what is it built for?

Blnk is an open source double-entry ledger in Go for teams building fintech products, wallets, banking infrastructure, payment systems and lending products. It provides the primitives for recording transactions, managing balances, reconciling external records and keeping financial state accurate.

How do I run Blnk locally?

The compose file starts an init job, a server, a worker, Redis and Postgres 16. The server image runs `blnk migrate up && blnk start`, so migrations are applied at startup, and the configuration is supplied through environment variables such as POSTGRES_DB and POSTGRES_SCHEMA, with the compose file at docker-compose.yaml.

What can Blnk do besides hold balances?

The ledger core covers balance monitoring, balance snapshots, historical balances, inflight transactions, scheduling, overdrafts and bulk transactions. On top of that there is reconciliation against external records using custom matching rules, and identity management with tokenization of PII linked to balances and transactions.

Does Blnk require Postgres and Redis?

Yes. The docker-compose.yaml file defines a postgres:16 service and a redis:7.2.4 service, and both the server and the worker declare a dependency on both of them. The image also installs the Postgres client version 16 for pg_dump.

What licence is Blnk released under?

The Apache License 2.0, with the licence file at the repository root. The project is open source to self-host and extend, and the same vendor also offers Blnk Cloud hosting and paid support plans for production integrations.

Official sources

  1. blnkfinance/blnk on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/blnkfinance-blnk.svg)](https://hysenlabs.com/projects/blnkfinance-blnk)

Was this useful?