Skip to content

ADR-040: SaaS usage metering and multi-tenant cost attribution

Status Accepted
Date 2026-04-15
Deciders CTO, Head of Architecture, Head of Data, CFO
Affects repos bank-platform, bank-risk-platform, bank-app

Status: Accepted — 2026-04-15

Context

The bank licenses its platform to smaller financial institutions as modular SaaS (BG-011). Licensees pay a combination of per-customer and per-facility (per-module) charges, plus variable consumption. To operate this commercially and maintain trust with licensees, the bank must:

  1. Meter actual usage accurately — per licensee, per module, per resource type
  2. Attribute real infrastructure costs to tenants — AWS and Snowflake
  3. Produce a transparent, near-real-time cost and usage report that licensees can inspect at any time
  4. Derive internal unit economics — cost to serve each module per customer, gross margin by licensee

Cost sources are heterogeneous: - AWS infrastructure — Lambda invocations, API Gateway calls, Kinesis throughput, S3 storage/requests, EventBridge, SQS, DynamoDB, Secrets Manager - Snowflake compute — analytics queries, ML inference via Cortex, Dynamic Table refresh cycles, data sharing egress - External data — Snowflake Marketplace subscriptions (market data), enrichment API calls (merchant data, geo), NZFMA direct feed

Options considered:

  1. Module-level instrumentation only — each module emits usage metrics; no AWS-level cost attribution. Simple but cannot close the loop to actual cost.
  2. AWS resource tagging + Cost Explorer API — tag all resources with tenant_id; pull AWS Cost Explorer daily. Provides accurate infrastructure cost attribution with no custom instrumentation at the module layer, but requires disciplined tagging governance.
  3. Third-party FinOps platform (CloudHealth, Apptio Cloudability, etc.) — mature tooling but adds vendor dependency and cost; does not cover Snowflake natively.
  4. Hybrid: module usage events + AWS tagging + Snowflake metering — module-layer events capture logical usage (API calls, ML inferences); AWS Cost Explorer captures physical infrastructure cost; Snowflake query_history / metering_history captures compute credits. Attribution joins at the Snowflake analytics layer.

Decision

Adopt Option 4 — hybrid metering.

Module usage events: All modules emit a structured bank-platform.usage_event EventBridge event on every billable operation. The event schema is standardised (see MOD-097). Events flow via Kinesis Firehose → S3 → Snowflake metering.usage_events. This creates a logical usage ledger independent of infrastructure provider.

AWS resource tagging: Every AWS resource created for a licensee tenant is tagged with tenant_id, module_id, and environment. The tagging contract is enforced via AWS Config rules and IaC (SST/CDK). AWS Cost Explorer is polled daily by MOD-098 and results written to metering.aws_cost_daily in Snowflake.

Snowflake compute attribution: Each licensee is assigned a dedicated Snowflake virtual warehouse for their analytics workloads. The warehouse name encodes the tenant_id. Where shared warehouse is used (small tenants), queries are tagged via ALTER SESSION SET QUERY_TAG = '{"tenant_id": "..."}'' and cost is attributed from snowflake.account_usage.query_history proportionally by credits_used. Results written to metering.snowflake_credit_daily.

Cost attribution model: A rate card (metering.cost_rates) maps resource types to $/unit. The attribution engine (MOD-098) multiplies usage events by the rate card to produce attributed cost. The rate card is updated when underlying AWS/Snowflake pricing changes. Infrastructure cost from Cost Explorer and Snowflake credits is attributed as a passthrough (actuals, not rate card) — licensees can see true cost if they opt into the transparency report.

Billing model:

Layer Basis Unit
Customer levy Per active customer on the platform $/customer/month
Facility fee Per activated module $/module/month
Variable consumption Per unit above included threshold $/unit (Snowflake credits, API calls, ML inferences, notifications, storage-GB)
Infrastructure passthrough Actual AWS cost tagged to tenant $/month (optional transparency feature)

Consequences

Positive: - Licensees can inspect their own usage and cost at any time — builds trust - Internal unit economics are available: gross margin per licensee, cost per module per customer - No single billing source — the hybrid approach survives provider changes - Tagging governance is enforced structurally (IaC + Config rules), not manually

Negative / trade-offs: - AWS Cost Explorer has 24–48 hour latency — infrastructure cost is always slightly retrospective - Snowflake shared-warehouse attribution is proportional (estimated) not exact; dedicated warehouses eliminate this for high-volume tenants - Tagging discipline must be maintained across all future module development — requires a pre-commit check in CI

Risk: If a module is deployed without correct tenant tagging, its AWS costs are unattributed and fall to the platform overhead bucket. Mitigation: IaC lint rule checks for required tags before deployment. Unattributed cost budget is monitored by MOD-098 and alerted if it exceeds a threshold.

Signoff

Name Role Date
Ross Millen Head of Architecture 2026-04-15
Ross Millen Head of Data 2026-04-15
Ross Millen CTO 2026-04-15

Capabilities

Capability Satisfying module Mode
CAP-140 SaaS usage metering & cost attribution MOD-097 Usage event collector AUTO
CAP-140 SaaS usage metering & cost attribution MOD-098 Cost attribution engine CALC
CAP-140 SaaS usage metering & cost attribution MOD-099 Usage & billing report AUTO

All ADRs Compiled 2026-05-22 from source/entities/adrs/ADR-040.yaml