Overview
The database schema is defined using Drizzle ORM inlib/drizzle/schema.ts. It consists of three main tables: users, subscriptions, and payments, with proper relationships and type safety.
Tables
Users Table
Stores user account information linking Supabase authentication with Dodo Payments customers.Fields
-
supabaseUserId (text, PRIMARY KEY)
- Links to Supabase Auth user ID
- Unique identifier for each user
-
dodoCustomerId (text, NOT NULL)
- Customer ID from Dodo Payments
- Used for payment operations
-
currentSubscriptionId (text, nullable)
- References active subscription
- Null for free tier users
-
createdAt (timestamp with timezone, NOT NULL)
- Account creation timestamp
- Stored as ISO string
-
updatedAt (timestamp with timezone, NOT NULL)
- Last account update timestamp
-
deletedAt (timestamp with timezone, nullable)
- Soft delete timestamp
- Null for active accounts
Subscriptions Table
Stores complete subscription details synced from Dodo Payments webhooks.Key Fields
Identification- subscriptionId (text, PRIMARY KEY) - Unique subscription identifier
- userId (text, FOREIGN KEY) - References users.supabaseUserId
- customerId (text) - Dodo Payments customer ID
- productId (text) - Product/plan identifier
- recurringPreTaxAmount (real) - Subscription amount before tax
- currency (text) - ISO currency code (e.g., “USD”)
- taxInclusive (boolean) - Whether price includes tax
- quantity (integer) - Number of subscription units
- status (text) - Subscription state: “active”, “cancelled”, “expired”, etc.
- createdAt (timestamp) - Subscription creation date
- cancelledAt (timestamp) - When subscription was cancelled
- cancelAtNextBillingDate (boolean) - Scheduled cancellation flag
- subscriptionPeriodInterval (text) - Period unit: “Month”, “Year”, etc.
- subscriptionPeriodCount (integer) - Number of periods
- paymentPeriodInterval (text) - Payment frequency unit
- paymentFrequencyCount (integer) - Payment frequency count
- nextBillingDate (timestamp) - Next charge date
- previousBillingDate (timestamp) - Last charge date
- trialPeriodDays (integer) - Free trial duration
- metadata (jsonb) - Custom metadata object
- billing (jsonb) - Billing address and details
- addons (jsonb) - Additional add-ons array
- discountId (text) - Applied discount/coupon ID
- onDemand (boolean) - On-demand subscription flag
- customerName (text) - Customer display name
- customerEmail (text) - Customer email address
Payments Table
Stores complete payment/invoice history for all transactions.Key Fields
Payment Core- paymentId (text, PRIMARY KEY) - Unique payment identifier
- status (text) - “succeeded”, “failed”, “processing”, “cancelled”
- totalAmount (real) - Total payment amount
- currency (text) - Payment currency
- createdAt (timestamp) - Payment creation timestamp
- updatedAt (timestamp) - Last update timestamp
- paymentMethod (text) - Payment method used
- paymentMethodType (text) - Type of payment method
- cardLastFour (text) - Last 4 digits of card
- cardNetwork (text) - “visa”, “mastercard”, etc.
- cardType (text) - “credit”, “debit”
- cardIssuingCountry (text) - Card issuing country code
- customerId (text) - Dodo Payments customer ID
- subscriptionId (text) - Related subscription ID
- brandId (text) - Brand identifier
- businessId (text) - Business identifier
- tax (real) - Tax amount
- settlementAmount (real) - Actual settlement amount
- settlementCurrency (text) - Settlement currency
- settlementTax (real) - Settlement tax amount
- discountId (text) - Applied discount
- customerName (text) - Customer name
- customerEmail (text) - Customer email
- billing (jsonb) - Billing address object
- metadata (jsonb) - Custom metadata
- webhookData (jsonb) - Complete webhook payload
- productCart (jsonb) - Products purchased
- paymentLink (text) - Payment link URL
- errorCode (text) - Error code if failed
- errorMessage (text) - Error description
- disputes (jsonb) - Dispute information
- refunds (jsonb) - Refund details
- digitalProductDelivered (boolean) - Delivery status flag
Relationships
User to Subscription (One-to-One)
- One current/active subscription (nullable)
- Many historical subscriptions
Subscription to User (Many-to-One)
Type Exports
The schema exports TypeScript types for type-safe database operations:Usage Example
Database Client
The database client is configured inlib/drizzle/client.ts using Drizzle ORM with PostgreSQL (via Supabase).
Migration Strategy
Schema changes should be:- Defined in
lib/drizzle/schema.ts - Generated as migrations using Drizzle Kit
- Applied to the database
- Synced with Supabase tables
