Stripe Billing Database Schema Diagram
If you bill with Stripe, these are the tables behind the API. Customers own subscriptions and payment methods; subscriptions are composed of subscription items that reference prices; prices belong to products; invoices collect line items and link to payment intents. This diagram maps the full Stripe billing model as PostgreSQL tables. The shape you would build when syncing Stripe objects into your own database or designing a Stripe-like billing system from scratch.
Last updated: 2026-09-03
Source: Original design by dbdiagramr, modeled on the Stripe billing API
Tables in the Stripe schema
| Column | Type | Nullable | Key |
|---|---|---|---|
| customers | |||
| id | text | No | PK |
| varchar | Yes | - | |
| name | varchar | Yes | - |
| phone | varchar | Yes | - |
| description | text | Yes | - |
| default_currency | varchar(3) | Yes | - |
| balance | integer | No | - |
| metadata | jsonb | Yes | - |
| created | timestamptz | No | - |
| deleted_at | timestamptz | Yes | - |
| products | |||
| id | text | No | PK |
| name | varchar | No | - |
| description | text | Yes | - |
| active | bool | No | - |
| type | varchar | No | - |
| metadata | jsonb | Yes | - |
| created | timestamptz | No | - |
| updated | timestamptz | Yes | - |
| prices | |||
| id | text | No | PK |
| product_id | text | No | - |
| unit_amount | integer | Yes | - |
| currency | varchar(3) | No | - |
| billing_interval | varchar | Yes | - |
| interval_count | integer | Yes | - |
| active | bool | No | - |
| type | varchar | No | - |
| created | timestamptz | No | - |
| subscriptions | |||
| id | text | No | PK |
| customer_id | text | No | - |
| status | varchar | No | - |
| collection_method | varchar | No | - |
| current_period_start | timestamptz | No | - |
| current_period_end | timestamptz | No | - |
| cancel_at_period_end | bool | No | - |
| canceled_at | timestamptz | Yes | - |
| trial_start | timestamptz | Yes | - |
| trial_end | timestamptz | Yes | - |
| default_payment_method_id | text | Yes | - |
| metadata | jsonb | Yes | - |
| created | timestamptz | No | - |
| subscription_items | |||
| id | text | No | PK |
| subscription_id | text | No | - |
| price_id | text | No | - |
| quantity | integer | No | - |
| created | timestamptz | No | - |
| invoices | |||
| id | text | No | PK |
| customer_id | text | No | - |
| subscription_id | text | Yes | - |
| status | varchar | No | - |
| amount_due | integer | No | - |
| amount_paid | integer | No | - |
| currency | varchar(3) | No | - |
| attempt_count | integer | No | - |
| due_date | timestamptz | Yes | - |
| paid_at | timestamptz | Yes | - |
| hosted_invoice_url | text | Yes | - |
| created | timestamptz | No | - |
| invoice_line_items | |||
| id | text | No | PK |
| invoice_id | text | No | - |
| price_id | text | Yes | - |
| amount | integer | No | - |
| currency | varchar(3) | No | - |
| description | text | Yes | - |
| quantity | integer | No | - |
| period_start | timestamptz | Yes | - |
| period_end | timestamptz | Yes | - |
| payment_methods | |||
| id | text | No | PK |
| customer_id | text | No | - |
| type | varchar | No | - |
| card_brand | varchar | Yes | - |
| card_last4 | varchar(4) | Yes | - |
| card_exp_month | smallint | Yes | - |
| card_exp_year | smallint | Yes | - |
| billing_country | varchar(2) | Yes | - |
| created | timestamptz | No | - |
| payment_intents | |||
| id | text | No | PK |
| customer_id | text | Yes | - |
| invoice_id | text | Yes | - |
| amount | integer | No | - |
| currency | varchar(3) | No | - |
| status | varchar | No | - |
| payment_method_id | text | Yes | - |
| client_secret | text | Yes | - |
| created | timestamptz | No | - |
Frequently asked questions
What tables does a Stripe billing schema need?
A Stripe-like billing schema needs customers, products, prices, subscriptions, subscription_items, invoices, invoice_line_items, payment_methods, and payment_intents. 9 tables covering the full subscription and payment lifecycle.
How do Stripe subscriptions relate to invoices and payments?
A customer has many subscriptions. Each subscription has many subscription_items (one per price). When a billing period ends, Stripe generates an invoice with line items; each invoice can have a payment_intent that charges the customer's default payment_method.
Explore more schemas
Visualize your own database
Paste your PostgreSQL connection string and get an interactive ER diagram of your own schema in under 10 seconds. No signup required.
Try it free →