AbsoluteJS

Billing

@absolutejs/billingv0.6.0betaPlatform & Infra

Pure-function usage billing for Bun apps — declare a priced plan and compute host-portable invoices in integer micros.

Turns metered usage into invoices without float drift or vendor lock-in. createPlan declares a priced product — flat base fee, per-dimension unit prices, graduated tiers, free allowances — and computeInvoice is a pure function from a usage snapshot to line items and a total, all in integer micros. It pairs with @absolutejs/metering for usage collection and leaves Stripe, QuickBooks, or another invoicing integration to the host, so previewing an upcoming invoice, re-pricing a past period, or dry-running a plan change is a plain function call.

#Installation

BASH
bun add @absolutejs/billing

#Capabilities

Overview

Provider-neutral pricing and invoice computation used by the hosted AbsoluteJS.ai platform.

@absolutejs/billing is the pure-function layer between @absolutejs/metering (which collects usage events) and an invoicing backend (Stripe, QuickBooks, an internal billing engine).

It does two things:

Show 5 more

createPlan(...) — declares a priced product: optional flat

base fee, per-dimension unit prices, optional graduated tiers, optional per-dimension free allowances.

computeInvoice({ plan, period, tenant, usage }) — pure

function that turns a Usage snapshot into an Invoice with line items and a total.

All money math is done in integer micros (1 micro = 1/1,000,000 of a currency unit — the same denomination Stripe stores prices in internally). Float drift is structurally impossible: a $0.0002 per-request price is 200 and rounding policy is explicit.

Pricing shapes

A PricedDimension is one of three:

Flat per-unit — { perUnitMicros: 200, unit: 1 }

Tiered (graduated) — { tiers: [{ upTo: 1_000_000, perUnitMicros: 200 }, { upTo: Infinity, perUnitMicros: 100 }] }

Show 10 more

Custom — { price: (chargedQuantity) => micros } (escape hatch for surge / caps / non-monotonic pricing)

Optional knobs:

freeTier — units subtracted before pricing

unit — divisor so bytesEgress priced as MB ↔ unit:

10241024

label — invoice line-item display name

Plan-level knobs:

basePriceMicros — flat fee per period

minimumChargeMicros — floor; an adjustment line item fills

any gap

Why pure?

The control plane needs to:

Preview an upcoming invoice before the period closes

Re-price a past period under a new plan ("what would this

Show 3 more

customer have paid on the proposed enterprise tier?")

Dry-run plan changes before publishing them

A pure cost-model function makes all three trivial — no Stripe SDK, no side effects, no IO. The Stripe push (or QuickBooks export, or mailed-PDF generator) lives outside this package, in @absolutejs/billing-adapters/.

Integer-micro money math

All prices are integer micros (1/1,000,000 of a currency unit — the same denomination Stripe stores internally), so float drift is structurally impossible and rounding policy is explicit.

Flexible pricing shapes

Each dimension is flat per-unit, graduated tiers, or a custom price function — the escape hatch for surge pricing, caps, and other non-monotonic schemes.

Free tiers and minimums

Per-dimension free allowances subtract before pricing, a plan-level base fee charges per period, and minimumChargeMicros floors the total with an adjustment line item.

Pure invoice computation

computeInvoice has no IO and no side effects, so you can preview invoices before the period closes, re-price history under a proposed plan, and dry-run changes before publishing.

Metering integration

Consumes Usage snapshots from @absolutejs/metering directly, and unit divisors let you price bytesEgress per MB or cpuMs per second without pre-converting.

Outcomes

What you can build

Model SaaS pricing

Declare provider-neutral plans with base prices, usage dimensions, free allowances, graduated tiers, minimum charges, labels, and explicit rounding.

Compute invoices deterministically

Preview, dry-run, and re-price usage snapshots without calling Stripe, QuickBooks, or another invoicing provider.

Hardening checklist

Production guidance

Preserve billing evidenceKeep all prices in integer micros, version the plan used for each period, retain the input usage snapshot, and push the resulting invoice through a separately idempotent provider adapter.

Follow in order

Troubleshooting path

1
An invoice total differs
Inspect each invoice line’s charged quantity, free allowance, unit divisor, tier, rounding policy, minimum-charge adjustment, and integer-micro amount before comparing external invoice output.

#@absolutejs/billing quick start

Partial snippet

# @absolutejs/billing

TS
import { createPlan, computeInvoice, formatMicros } from "@absolutejs/billing";

const plan = createPlan({
  name: "pro",
  currency: "usd",
  basePriceMicros: 20_000_000, // $20/mo
  pricedDimensions: {
    requests: { perUnitMicros: 200, freeTier: 1_000_000 },
    cpuMs: { perUnitMicros: 50, unit: 1000, freeTier: 60_000 * 60 * 10 },
    bytesEgress: {
      perUnitMicros: 100,
      unit: 1024 * 1024,
      freeTier: 100 * 1024 * 1024,
    },
    hibernationGbSeconds: { perUnitMicros: 5 },
  },
});

const invoice = computeInvoice({
  plan,
  tenant: "acme",
  period: { start, end },
  usage, // a Usage from @absolutejs/metering
});

console.log(formatMicros(invoice.totalMicros, invoice.currency));
// "27.50 USD"

#Quick Start

Partial snippet

Declare a plan with a base fee, per-dimension prices, and free allowances, then compute an invoice from a metering snapshot.

TS
import {
  createPlan,
  computeInvoice,
  formatMicros,
} from '@absolutejs/billing';

const plan = createPlan({
  name: 'pro',
  currency: 'usd',
  basePriceMicros: 20_000_000, // $20/mo
  pricedDimensions: {
    requests: { perUnitMicros: 200, freeTier: 1_000_000 },
    cpuMs: {
      perUnitMicros: 50,
      unit: 1000,
      freeTier: 60_000 * 60 * 10,
    },
    bytesEgress: {
      perUnitMicros: 100,
      unit: 1024 * 1024,
      freeTier: 100 * 1024 * 1024,
    },
  },
});

const invoice = computeInvoice({
  plan,
  tenant: 'acme',
  period: { start, end },
  usage, // a Usage from @absolutejs/metering
});

console.log(formatMicros(invoice.totalMicros, invoice.currency));
// "27.50 USD"

#Tiered Pricing

Partial snippet

Graduated tiers price each band separately — the first million requests at one rate, everything beyond at another.

TS
const plan = createPlan({
  name: 'scale',
  currency: 'usd',
  pricedDimensions: {
    requests: {
      tiers: [
        { upTo: 1_000_000, perUnitMicros: 200 },
        { upTo: Infinity, perUnitMicros: 100 },
      ],
    },
  },
});
Host-owned invoicing
This package is the cost model only. Your host application pushes the computed invoice to Stripe, QuickBooks, an internal billing engine, or a PDF generator, keeping the pricing math pure and testable.
Beta
The package is pre-1.0. The plan and invoice shapes are settling, but expect minor API adjustments before a stable release.

#API reference

Search the declarations exported by the current package type files. Expand a symbol to inspect its source-backed signature.

21 symbols
MicrostypePermalink

@absolutejs/billing — cost-model substrate for the AbsoluteJS PaaS. Two pieces: - createPlan(...) — declarative pricing config: optional flat base fee + per-dimension unit prices, with optional graduated tiers and free-tier allowances per dimension. - computeInvoice({ plan, period, tenant, usage, currency? }) — pure function that turns a @absolutejs/metering-shaped Usage snapshot (or any record of metered numbers) into an Invoice of line items + total. All money math is done in integer micros (1

TS
type Micros = number;
Exported from @absolutejs/billing

Current package surface

What ships today

@absolutejs/billingv0.6.0 · betaPlatform & InfranpmSource
4entry points37symbols

Import surface · click to copy