Skip to main content

Context

DEC-G3 committed to Vercel-style pricing: published unit prices, included allowances, measured consumption, a projected-spend panel and tenant-configurable spend caps. All of that rests on a measurement that is frequent enough to be actionable and cheap enough to run for every tenant forever. DEC-G1 settled it at every 30 minutes with deltas. Computing consumption on demand would put an aggregate query on a dashboard path; daily snapshots would let a tenant blow through a quota for 23 hours before anyone noticed. The measurement has contractual weight: the ToS names these snapshots as the evidentiary basis for billing. That is why they are append-only and why a correction is a new row, never an edit.

Scope (normative)

  • core.usage_snapshots, append-only, monthly partitioned, every 30 minutes per tenant.
  • core.billable_metrics: parametric — marketable contacts, tracked events, messages by channel, storage.
  • Delta computation between t1 and t2 so consumption never needs a scan.
  • The marketable-contact count, using the predicate defined in FS-CORE-0004.
  • Threshold alerts at 80 / 90 / 100% through the platform’s own notification system.
  • Enforcement hooks: grace, hard stop, or overage per metric, configurable per tenant from Ops.

Non-scope (normative)

  • The rating engine — it consumes these snapshots; it is its own epic (ADR-016).
  • Invoicing and charging — Fintoc, Paddle, LibreDTE.
  • The consumption dashboard UI — frontend/console.

Behaviour (normative)

  1. Snapshots run every 30 minutes for every tenant, on cron fan-out. Not tiered — the cost is low and a tenant discovering an overage a day late is a support problem for us.
  2. Each row stores the absolute value and the delta since the previous snapshot. Deltas make billing a sum instead of a scan.
  3. The table is append-only. A correction is a new row with a correction_of reference; editing a snapshot would destroy the evidentiary value the ToS relies on.
  4. Marketable contacts use the predicate from FS-CORE-0004 — one definition, shared, so metering and messaging can never disagree about who is billable.
  5. Alerts at 80, 90 and 100% are sent through the platform’s own notification cascade. Building a second delivery path for our own alerts would put them outside the rules everything else obeys.
  6. Enforcement per metric is configurable per tenant from Softcrum Ops (DEC-G2). Defaults: contacts grace + notice, messages hard at 110%, events soft with overage.
  7. A spend cap is the tenant’s self-service face of enforcement: reaching it applies the same stop the operator would.
  8. A missed snapshot window is recorded as missing, never interpolated. An interpolated number in a billing basis is a number we cannot defend.
  9. Partitioned monthly; retention follows the plan, with the legal minimum applying independently.

Data (normative)

API (normative)

Events (normative)

core.usage.threshold_crossed on the outbox at 80, 90 and 100%, which is what drives the alert campaign through messaging.

Acceptance criteria (normative)

  1. Snapshots land every 30 minutes for every tenant, verified over a 24-hour synthetic run.
  2. The sum of deltas over a cycle equals the difference of absolutes at its endpoints.
  3. The marketable-contact count matches the messaging module’s own view for the same tenant and instant.
  4. Crossing 80% emits once and does not re-emit while it stays above.
  5. A missed window is recorded as missing and is visibly absent, not interpolated.
  6. A spend cap applies the configured enforcement within one snapshot window.
  7. Corrections append with correction_of and leave the original readable.
  8. Negative: no code path updates or deletes a snapshot row.

Execution

Asynchronous pipeline. Cron fan-out in backend/scheduler, computation in backend/workers, read endpoints in backend/api.

Open questions

Changelog

Delivery record

Not implemented yet.