Back to Blog

What is Numscript and Why is it Awesome?

What is Numscript and Why is it Awesome?

A declarative financial transaction DSL for both engineering and finance teams

Numscript is Formance’s ledger DSL for atomic, auditable transactions—simplifying complex money movement into clear, programmable intent.

LedgerProduct

Every team that builds payments infrastructure fights the same battle. A simple “move funds from A to B” quickly becomes a system of chained API calls, balance checks, and conditional logic, with each addition introducing risk. Scaling that code across services only adds more fragility: Race conditions, rounding errors, and reconciliation noise that slow audits and make systems brittle.

What should be a single atomic transaction becomes an exercise in orchestration and cleanup. You write more safeguards, build more retries, and still can’t guarantee that everything posts exactly once. Engineering shouldn’t have to compensate for language gaps. Money movement deserves a first-class abstraction that’s precise, readable, and truly atomic.

That’s why we built Numscript.

What is Numscript?

General-purpose code can tell a computer how to move money, step by step, but it can’t easily express what the transaction is meant to do or guarantee that it happens atomically. When something fails midstream, balances fall out of sync, logs fill with partial data, and no one can reconstruct what really happened.

That’s why teams end up spending as much time reconciling their ledgers as they do building new features. Numscript changes that by giving money movement its own language.

Numscript is Formance’s domain-specific language (DSL) for programmable ledgers—a way to describe money movement that’s both human-readable and machine-safe. Instead of writing backend code to orchestrate every debit, credit, and balance check, you describe the intent of a transaction: “Move X from A to B under these conditions.”

From there, the Formance programmable ledger executes that intent atomically and immutably. Every posting succeeds or fails as one complete unit without race conditions, partial updates, or manual reconciliation.

Because Numscript is declarative, you focus on what should happen, not how to make it happen. It’s simple enough for an accountant to read, yet precise enough for engineers to trust. The result is a shared language across teams: Developers see reliable logic, finance sees traceable transactions, and auditors see a single source of truth.

Even better, Numscript isn’t locked inside the Formance stack. It’s openly documented, open-sourced, and includes a standalone interpreter you can experiment with or embed elsewhere. That makes it portable, extensible, and future-proof, qualities you want in your financial infrastructure. Numscript turns the logic of money movement into code that’s as clear, atomic, and auditable as the ledger itself.

Why Numscript is Awesome

Numscript shines whenever you’d normally stitch together multiple API calls in the hopes that  they behave atomically. In a programmable ledger, the ledger DSL becomes the source of truth: You describe intent once; the ledger executes atomic transactions and records them immutably. And Numscript uses only integer math with built-in rounding rules combined with Unambiguous Monetary Notation to ensure deterministic rounding without errors, which is impossible to ensure with floating-point math.

Here’s an example:

A) Marketplace payout (splits + fees)

Let’s say you operate a rideshare marketplace, and you need to be able to accept customer payments, pay drivers, and support your corporate mission of donating to charity. Here’s what a traditional approach looks like:

Imperative/JSON mindset (what teams usually build):

  • Move customer payment into a clearing account
  • Forward to the ride’s escrow or holding account
  • Split 85% to the driver, 10% of the remainder to charity, and the rest to platform fees
  • Handle rounding, retries, and partial failure paths manually

That’s a lot of work, and a lot of points of failure.

Numscript provides a streamlined path:

Numscript (declarative, atomic):

// Capture payment of $5.99
send [USD/2 599] (
	source = @world
	destination = @payments:001
)

// Move payment to clearing account
send [USD/2 599] (
	source = @payments:001
	destination = @rides:0234
)

// Split the %5.99 payment among the driver, our charity, and our fee
send [USD/2 599] (
	source = @rides:0234
	destination = {
		85% to @drivers:042
		remaining to {
			10% to @charity
			remaining to @platform:fees
		}
	}
)

One script expresses the whole flow; the ledger commits all postings or none, leaving an audit-ready record of intent and outcome.

B) Cascading sources (draw from A, then B, with a cap)

Sometimes a transaction should pull from multiple funding sources—but with limits.

For example, a customer might have a coupon that offers 10% off of an order, up to a maximum of $20.00. The remaining charge will be sourced from the customer’s wallet.

Imperative/JSON mindset:

  • Check wallet balance
  • If insufficient, top up from the payments account
  • Enforce “take at most 20 USD from the coupon pool”
  • Race-proof the sequence

In a typical system, this requires multiple calls, balance checks, and branching logic to enforce the cap. In Numscript, it’s one atomic declaration:

Numscript (ordered sources with a max):

// the FALL24 coupon gets you 10% value off for a maximum of $20
// pay $299.-
send [USD/2 29900] (
  source = {
    10% from {
      max [USD/2 2000] from @coupons:FALL24
      @users:1234
    }
    remaining from @users:1234
  }
  destination = @payments:4567
)

This declares both order and constraint in the ledger DSL, ensuring execution is atomic to avoid multi-call fragility and reconciliation noise.

C) Penny handling & deterministic rounding (no float bugs)

Splits rarely divide cleanly. Numscript avoids floating-point math and deterministically distributes remainders in a predictable order. Imagine we need to split BTC 0.00000943 evenly between two accounts:

// Split BTC 0.00000943 evenly between two accounts
send [BTC/8 943] (
	source = @users:1234
	destination = {
		50% to @users:4567
		50% to @users:7890
	}
)

The result: @users:4567 gets BTC 0.00000472 and @users:7890 gets BTC 0.00000471 (reverse the order to flip which side receives the extra unit). For five equal splits of BTC 0.00000943, Numscript floors to BTC 0.00000188 each then allocates the remaining units from the top of the list down, so there are no invisible fractions or “mystery money.”

Why Choose Numscript for Your Ledger Logic?

Teams have been writing custom ledger logic for years and paying for it in complexity. Numscript replaces that fragile, code-heavy approach with something safer, simpler, and clearer.

Safety Comes First

When you hand-code transaction logic, you’re juggling state across multiple systems, locking accounts, checking balances, and hoping nothing changes mid-call. Each extra API introduces another failure point: A timeout, a duplicate retry, a balance that’s no longer accurate. Concurrency bugs hide in the gaps between services, and race conditions creep in as systems scale. Even the best rollback scripts can’t guarantee full consistency once partial postings have gone through.

By replacing pages of JSON and chains of REST API calls with a single, declarative script, Numscript cuts development time, reduces failure points, and makes every transaction predictable and auditable. The ledger handles locking and sequencing automatically, so the kinds of data drift and cleanup headaches that plague traditional systems simply never occur. As a result, teams spend less time debugging and more time building features that move the business forward.

Clarity is Transformative

Even when a system is fast and reliable, miscommunication can still bring it down. Engineers think in code, accountants think in ledgers, and product teams translate between them. Each group describes the same transaction in a different language—how money moved, why it moved, and whether it reconciled. Even simple changes to the process can result in endless clarification meetings, conflicting assumptions, and delayed releases. Unfortunately, when issues arise, teams often end up debating interpretations rather than addressing the core problem, because everyone’s speaking a different language.

Numscript eliminates that translation layer. It gives everyone a shared, human-readable language for money movement. Developers get a precise, declarative syntax for modeling complex logic. Finance and compliance teams see the same script and can verify its intent without writing (or learning) a line of code. Auditors can read exactly what was executed, not a paraphrase in documentation. Reviews move faster, errors surface earlier, and every team speaks from the same source of truth, resulting in better communication between departments and improved control over how value flows through the business.

And It’s Open!

Plus, you can trust it. Numscript is open source, fully documented, and implemented in portable Go. It’s based on years of real-world payment experience, not theory, and it continues to evolve alongside the needs of modern financial platforms.

Try It Yourself: The Programmable Ledger Advantage

At its core, Numscript represents a shift in how to think about programmable ledgers: From procedural code that manages money to a ledger DSL that describes it.

By making transactions atomic, declarative, and auditable, Numscript removes layers of orchestration and restores clarity to the one system that can’t afford ambiguity: The core ledger. For engineers, that means cleaner integrations and fewer failure modes. For CFOs and product leaders, it means transparent, verifiable logic that scales with the business.

Numscript is open-sourced, fully documented, and ready to try in the Numscript Playground. Load an example, edit it, and see your transaction logic come to life.