← All three datastores

Billing datastore

Plans, entitlements, subscriptions, invoices and metered usage. Holds no card data — only a provider token, brand and last four.

govdeets_billing · BILLING_DATABASE_URL · prisma/billing/schema.prisma

GovDEETS — Billing datastore

Generated by prisma-markdown

Accounts

BillingAccount

The billing side of an organization. One per organization, created lazily the first time the org needs a plan (which includes being put on free).

Properties as follows:

  • id:
  • organizationId

    Opaque pointer to Organization in the core datastore. Unique because an organization has exactly one billing account; not a foreign key because that table is in a different database.

  • provider:
  • providerCustomerId

    The provider's customer identifier (cus_… at Stripe). Null while the account has never needed a payment method — a free plan never does.

  • billingEmail

    The one address invoices go to. Deliberately not joined to any user: finance contacts leave, and billing should not break when they do.

  • currency:
  • taxId: Tax identifier as supplied by the customer, for invoice rendering.
  • status:
  • delinquentSince: Set when a delinquent account has been locked out of paid features.
  • createdAt:
  • updatedAt:

PaymentMethodRef

A stored payment instrument, by reference. Everything sensitive stays at the provider; these columns exist only so the settings page can show which card is on file without a round trip.

Properties as follows:

  • id:
  • billingAccountId:
  • providerPaymentMethodId:
  • kind: card, us_bank_account, link, …
  • brand:
  • last4:
  • expMonth:
  • expYear:
  • isDefault:
  • createdAt:
  • detachedAt:

Subscriptions

Plan

A purchasable plan. Plans are seeded and version-controlled rather than created at runtime, so the entitlement matrix is reviewable in a diff.

Properties as follows:

  • id:
  • key

    Stable machine key used in code and in the cached planKey on Organization: free, team, business, enterprise.

  • name:
  • description:
  • priceCents:
  • currency:
  • interval:
  • providerPriceId

    The provider's price object (price_… at Stripe). Null for plans that are never charged, and for the mock provider.

  • isPublic

    Whether the plan appears on the public pricing page. Enterprise deals are real Plans that simply aren't listed.

  • sortOrder:
  • createdAt:
  • updatedAt:

PlanEntitlement

One capability granted by a plan. This is the whole authorization vocabulary on the billing side: a feature key, whether it is on, and an optional numeric ceiling.

limit semantics: null means unlimited, and any non-null value is the inclusive maximum. enabled = false denies the feature outright regardless of limit.

Properties as follows:

  • id:
  • planId:
  • feature

    Dotted feature key — seats, watch.max, watch.triggers.max, api.v1.read, api.v1.history, api.v1.aggregate, api.rate.perMinute, integration.slack, export.bulk.

  • enabled:
  • limit:

Subscription

An organization's current (or past) subscription to a plan.

Properties as follows:

  • id:
  • billingAccountId:
  • planId:
  • status:
  • providerSubscriptionId:
  • seats

    Purchased seat count. Enforcement happens in core, which is the only database that knows how many memberships actually exist.

  • currentPeriodStart:
  • currentPeriodEnd:
  • cancelAtPeriodEnd:
  • trialEndsAt:
  • canceledAt:
  • createdAt:
  • updatedAt:

EntitlementOverride

A negotiated exception layered on top of the plan's entitlements — the "we'll throw in the history API" that sales agreed to. Kept separate from PlanEntitlement so the plan definition stays canonical and the exception stays visible and expirable.

Properties as follows:

  • id:
  • subscriptionId:
  • feature:
  • enabled:
  • limit:
  • note: Why this exists, so the next person to read it isn't guessing.
  • expiresAt:
  • createdAt:

Invoicing

Invoice

A mirror of an invoice held at the provider, kept locally so billing history renders without an API call and survives the provider being unreachable or replaced.

Properties as follows:

  • id:
  • billingAccountId:
  • providerInvoiceId:
  • number: Human-facing invoice number.
  • status:
  • amountDueCents:
  • amountPaidCents:
  • currency:
  • periodStart:
  • periodEnd:
  • issuedAt:
  • paidAt:
  • dueAt:
  • hostedInvoiceUrl:
  • pdfUrl:
  • createdAt:

UsageRecord

Metered usage, pre-aggregated into windows rather than stored per request. The per-request detail lives in core as ApiRequestLog, where it belongs with the rest of the operational data; only the billable rollup crosses into this database.

Properties as follows:

  • id:
  • billingAccountId:
  • feature

    Matches a PlanEntitlement feature key, so a limit can be checked against the same vocabulary that granted it.

  • quantity:
  • windowStart:
  • windowEnd:
  • reportedAt: Set once the rollup has been reported to the provider for metered billing.
  • createdAt:
  • updatedAt:

BillingEvent

Raw provider webhook events, recorded before they are acted on. Keeping them makes payment state reconstructible after a bug, and providerEventId being unique is what makes webhook delivery idempotent.

Properties as follows:

  • id:
  • billingAccountId:
  • provider:
  • providerEventId:
  • kind:
  • payload:
  • receivedAt:
  • processedAt:
  • error: