Below is a production-grade Billing & Subscription database schema, inspired by Stripe / Chargebee / Zuora, designed for multi-tenant SaaS systems.
Iโll explain:
- All tables
- Why they exist
- Key relationships
- Design decisions (immutability, lifecycle, auditability)

๐งพ SaaS Billing & Subscription Database Schema (Complete Guide)
๐ง Core Design Principles
Before schema, understand the rules:
โ
Plans are immutable pricing units
โ
Subscriptions are stateful lifecycles
โ
Invoices are historical & never change
โ
Payments are append-only records
โ
Everything is tenant-isolated
๐งฑ High-Level Architecture
Tenant
โโโ Customers
โโโ Products
โ โโโ Plans
โ โโโ Subscriptions
โ โโโ Invoices
โ โโโ Payments
โโโ Usage Records (optional)
1๏ธโฃ tenants
๐ Who owns the billing setup
tenants (
id UUID PK,
name TEXT,
status TEXT,
created_at TIMESTAMPTZ
)
Why?
- Enables multi-tenant SaaS
- Data isolation
- Tenant-specific pricing
2๏ธโฃ customers
๐ Who pays the money
customers (
id UUID PK,
tenant_id UUID FK,
email TEXT,
name TEXT,
external_ref TEXT, -- CRM / Auth ID
created_at TIMESTAMPTZ
)
Why?
- A tenant can have many customers
- Decouples auth from billing
- Required for invoicing
3๏ธโฃ products
๐ What is being sold (features)
products (
id UUID PK,
tenant_id UUID FK,
name TEXT,
description TEXT,
active BOOLEAN
)
Why?
- Logical grouping of plans
- Feature-based products
- One product โ many plans
4๏ธโฃ plans (IMMUTABLE)
๐ Pricing + billing rules
plans (
id UUID PK,
tenant_id UUID FK,
product_id UUID FK,
plan_key TEXT,
billing_period INTERVAL,
interval_count INT,
amount_cents BIGINT,
currency CHAR(3),
trial_days INT,
active BOOLEAN,
created_at TIMESTAMPTZ,
UNIQUE (tenant_id, plan_key)
)
Why?
- Defines money
- Never update price or interval
- New price = new plan
๐ Immutable after use
5๏ธโฃ subscriptions (STATEFUL)
๐ Customerโs active contract
subscriptions (
id UUID PK,
tenant_id UUID FK,
customer_id UUID FK,
plan_id UUID FK,
status TEXT,
start_date TIMESTAMPTZ,
current_period_start TIMESTAMPTZ,
current_period_end TIMESTAMPTZ,
cancel_at_period_end BOOLEAN,
canceled_at TIMESTAMPTZ
)
Why?
- Tracks lifecycle
- Allows upgrades/downgrades
- Does NOT store pricing
Subscription States
INCOMPLETE
ACTIVE
PAST_DUE
CANCELED
EXPIRED
6๏ธโฃ invoices (HISTORICAL)
๐ Bill generated for a period
invoices (
id UUID PK,
tenant_id UUID FK,
subscription_id UUID FK,
invoice_number TEXT,
status TEXT,
subtotal_cents BIGINT,
tax_cents BIGINT,
total_cents BIGINT,
currency CHAR(3),
issued_at TIMESTAMPTZ,
due_at TIMESTAMPTZ
)
Why?
- Legal & financial record
- Never edited after issuance
- Basis for payments & refunds
7๏ธโฃ invoice_items
๐ Line-level billing breakdown
invoice_items (
id UUID PK,
invoice_id UUID FK,
description TEXT,
amount_cents BIGINT,
quantity INT
)
Why?
- Supports proration
- Discounts
- Add-ons
- Usage charges
8๏ธโฃ payments
๐ Money movement
payments (
id UUID PK,
tenant_id UUID FK,
invoice_id UUID FK,
provider TEXT,
provider_payment_id TEXT,
status TEXT,
amount_cents BIGINT,
currency CHAR(3),
paid_at TIMESTAMPTZ
)
Why?
- Append-only ledger
- Multiple attempts per invoice
- Gateway-agnostic
9๏ธโฃ payment_methods
๐ Stored payment instruments
payment_methods (
id UUID PK,
customer_id UUID FK,
provider TEXT,
token TEXT,
is_default BOOLEAN
)
Why?
- PCI compliance
- Reusable cards
- Auto-billing support
๐ usage_records (Optional โ Metered Billing)
๐ Pay-as-you-go usage
usage_records (
id UUID PK,
subscription_id UUID FK,
metric TEXT,
quantity BIGINT,
recorded_at TIMESTAMPTZ
)
Why?
- API calls
- Storage usage
- Seat-based billing
๐ Relationships Summary
| Entity | Relationship |
|---|---|
| Tenant | owns everything |
| Product | has many plans |
| Plan | referenced by subscriptions |
| Subscription | generates invoices |
| Invoice | has invoice_items |
| Invoice | paid by payments |
๐ Critical Design Rules (Do NOT Break)
โ Never update plans.amount
โ Never delete invoices
โ Never modify paid invoices
โ Never store money in subscriptions
๐ง Mental Model (Golden Rule)
Plans define money
Subscriptions define time
Invoices define history
Payments define truth
๐ Final Thoughts
This schema:
โ Scales to millions of subscriptions
โ Supports upgrades, proration, usage billing
โ Is audit-safe & finance-friendly
โ Matches Stripe-level design
Read other awesome articles inย Medium.com or in akcoding’s posts.
OR
Join us on YouTube Channel
OR Scan the QR Code to Directly open the Channel ๐

