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
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.
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 →