DEV Community

Akram Ashraf
Akram Ashraf

Posted on

Building a Double-Entry Accounting Engine in Node.js (Open Source — ledgerstack-core)

Most backend developers eventually face this problem:

I need accounting inside my app, but I don’t want to build a full ERP.

Whether you are building:

  • SaaS platform
  • Billing system
  • ERP
  • POS
  • Fintech app
  • Multi-tenant system

you will need:

  • Double-entry accounting
  • Trial balance
  • Balance sheet
  • Ledger
  • Financial year
  • Voucher system

There are many accounting softwares, but very few developer-friendly accounting engines for Node.js.

So I built one.


🚀 Introducing ledgerstack-core

npm:

https://www.npmjs.com/package/ledgerstack-core

ledgerstack-core is a double-entry accounting engine for Node.js designed for:

  • Multi-tenant SaaS apps
  • High performance systems
  • SQL databases
  • Worker-based processing
  • Cache-based reports

Supported DBs:

  • PostgreSQL
  • MySQL
  • SQLite
  • MSSQL

Why not use existing libraries?

Most accounting libraries are:

  • Too simple (no balance sheet / no year / no groups)
  • Too complex (full ERP)
  • Not multi-tenant
  • Slow with large data
  • Not DB-agnostic

I needed something like:

initAccounts()
createVoucher()
getTrialBalance()
processJobs()
Enter fullscreen mode Exit fullscreen mode

but production-ready.

So I built ledgerstack-core.


Features

✅ Double-entry accounting

  • Debit = Credit enforced
  • Voucher-based system
  • Journal / Payment / Receipt / Sales / Purchase

✅ Multi-tenant ready

  • Tenant
  • Company
  • Financial year
  • Period lock

✅ Cache-based performance

Reports use cache tables instead of aggregates.

account_balance_cache
account_daily_balance
balance_jobs
Enter fullscreen mode Exit fullscreen mode

This keeps reports fast even with large data.

✅ Worker-based recalculation

Voucher change → queue job → worker updates cache

No slow API calls.

✅ Default groups (like Tally)

Seeded automatically:

  • Assets
  • Liabilities
  • Income
  • Expenses
  • Equity
  • Cash
  • Bank
  • Profit & Loss
  • Suspense

✅ Built-in reports

  • Trial Balance
  • Ledger
  • Ledger with running balance
  • Balance Sheet
  • Profit & Loss
  • Day Book
  • Cash Book
  • Group Summary

Architecture

App
  ↓
ledgerstack-core
  ↓
adapter
  ↓
database
Enter fullscreen mode Exit fullscreen mode

Modules:

  • init
  • adapter
  • accounts
  • vouchers
  • balance
  • cache
  • reports
  • worker
  • audit
  • currency
  • cost center

Example Usage

import {
  initAccounts,
  migrate,
  createAccount,
  createVoucher,
  getTrialBalance,
  processJobs
} from "ledgerstack-core"
Enter fullscreen mode Exit fullscreen mode

Init

await initAccounts({
  adapter,
  tenant: true,
  worker: true
})

await migrate()
Enter fullscreen mode Exit fullscreen mode

Create account

await createAccount({
  name: "Cash",
  group: "Cash-in-Hand"
})
Enter fullscreen mode Exit fullscreen mode

Create voucher

await createVoucher({
  date: new Date(),
  entries: [
    { account: "Cash", debit: 1000 },
    { account: "Sales", credit: 1000 }
  ]
})
Enter fullscreen mode Exit fullscreen mode

Run worker

await processJobs()
Enter fullscreen mode Exit fullscreen mode

Get report

const tb = await getTrialBalance()
Enter fullscreen mode Exit fullscreen mode

Why cache-based accounting?

Most systems do:

SUM(entries)
Enter fullscreen mode Exit fullscreen mode

This becomes slow.

ledgerstack uses:

balance_cache
daily_cache
worker_jobs
Enter fullscreen mode Exit fullscreen mode

So reports stay fast.


Who is this for?

  • Backend developers
  • SaaS builders
  • ERP developers
  • Fintech apps
  • Internal tools

Not for UI users.


npm

https://www.npmjs.com/package/ledgerstack-core


GitHub

https://github.com/akram-ashraf/ledgerstack-core


Future plans

  • inventory module
  • tax module
  • report builder
  • plugin system
  • auto docs from TS

Feedback welcome

If you are building accounting in Node.js, try it and share feedback.
This project is still evolving.

Top comments (0)