CLOSE
Database Design and Schema

Database Design and Schema

Updated on 30 Jun, 2026 23 mins read 1,148 views

Let's design the database schema for the platform.

Choosing the Database

For a platform like this, the ideal choice is PostgreSQL, because:

  • It supports relational data modeling (users <-> posts <-> subscriptions).
  • It's ACID-compliant โ€“ ensuring reliability even during concurrent writes.
  • It offers full-text search, JSON support, and great indexing options.

ORM layer: Prisma (for Node.js)

Core Entities Overview

Before diving into tables, let's identity the main entities and their relationships.

EntityDescription
UserRepresents both creators and readers
PostA blog/newsletter entry written by a creator
SubscriptionTracks which reader follows which creator
PaymentRecords transactions and plans
EmailQueueManages pending newsletters
AnalyticsStores engagement metrics (views, clicks, etc.)
CommentReader interaction with posts
TagCategorizes posts for discoverability

Entity-Relationship (ER) Diagram

     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚    User      โ”‚
     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
     โ”‚ id (PK)      โ”‚
     โ”‚ name          โ”‚
     โ”‚ email         โ”‚
     โ”‚ role          โ”‚
     โ”‚ password_hash โ”‚
     โ”‚ created_at    โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚1
           โ”‚
           โ”‚โˆž
     โ”Œโ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚    Post       โ”‚
     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
     โ”‚ id (PK)       โ”‚
     โ”‚ author_id (FK)โ”‚
     โ”‚ title         โ”‚
     โ”‚ content       โ”‚
     โ”‚ status        โ”‚
     โ”‚ created_at    โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
           โ”‚
           โ”‚โˆž
     โ”Œโ”€โ”€โ”€โ”€โ”€โ–ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚   Comment    โ”‚
     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
     โ”‚ id (PK)      โ”‚
     โ”‚ post_id (FK) โ”‚
     โ”‚ user_id (FK) โ”‚
     โ”‚ content      โ”‚
     โ”‚ created_at   โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚ Subscription โ”‚
     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
     โ”‚ id (PK)      โ”‚
     โ”‚ reader_id FK โ”‚
     โ”‚ creator_id FKโ”‚
     โ”‚ plan_type    โ”‚
     โ”‚ is_active    โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚   Payment    โ”‚
     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
     โ”‚ id (PK)      โ”‚
     โ”‚ subscription_id (FK)โ”‚
     โ”‚ amount        โ”‚
     โ”‚ currency      โ”‚
     โ”‚ status        โ”‚
     โ”‚ created_at    โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

     โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
     โ”‚   EmailQueue โ”‚
     โ”‚โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”‚
     โ”‚ id (PK)      โ”‚
     โ”‚ post_id (FK) โ”‚
     โ”‚ recipient_id โ”‚
     โ”‚ status       โ”‚
     โ”‚ sent_at      โ”‚
     โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Detailed Table Design

1 User Table

ColumnTypeDescription
idUUIDPrimary key
nameVARCHAR(100)User name
emailVARCHAR(150)Unique
password_hashTEXTSecurely stored password
roleENUM('reader','creator','admin')Role type
bioTEXTCreator bio
profile_imageTEXTURL to avatar
created_atTIMESTAMPDefault now()

Each user can be both creator and a reader depending on context.

2 Post Table

ColumnTypeDescription
idUUIDPrimary key
author_idUUID (FK)References user.id
titleVARCHAR(255)Post title
slugVARCHAR(255)URL-friendly ID
contentTEXTBody content
visibilityENUM('public','paid','draft')Visibility level
created_atTIMESTAMPCreated time
updated_atTIMESTAMPLast updated
published_atTIMESTAMPPublish date

3 Comments Table

ColumnTypeDescription
idUUIDPrimary key
post_idUUID (FK)References post.id
user_idUUID (FK)References user.id
contentTEXTComment text
created_atTIMESTAMPCommented time

4 Subscription Table

ColumnTypeDescription
idUUIDPrimary key
reader_idUUID (FK)References user.id
creator_idUUID (FK)References user.id
plan_typeENUM('free','paid')Subscription level
start_dateTIMESTAMPStart time
end_dateTIMESTAMPRenewal/cancel date
is_activeBOOLEANCurrent status

5 Payment Table

ColumnTypeDescription
idUUIDPrimary key
subscription_idUUID (FK)References subscription.id
amountDECIMAL(10,2)Amount paid
currencyVARCHAR(10)e.g. USD, INR
stripe_txn_idVARCHAR(255)External transaction
statusENUM('success','failed','pending')Payment status
created_atTIMESTAMPPayment date

6 EmailQueue Table

ColumnTypeDescription
idUUIDPrimary key
post_idUUID (FK)References post.id
recipient_idUUID (FK)References user.id
statusENUM('pending','sent','failed')Delivery status
sent_atTIMESTAMPSent timestamp

This helps implement asynchronous email dispatch โ€“ ensuring reliability and retry logic.

7 Analytics Table

ColumnTypeDescription
idUUIDPrimary key
post_idUUID (FK)References post.id
viewsINTNumber of views
clicksINTClick count
email_opensINTEmail open count
created_atTIMESTAMPTime recorded

8 Tag Table

ColumnTypeDescription
idUUIDPrimary key
nameVARCHAR(50)Tag name
slugVARCHAR(50)URL-friendly tag
created_atTIMESTAMPCreation date

and a PostTag junction table (many-to-many):

| post_id (FK) | tag_id (FK) |

Relationship Summary

RelationshipTypeDescription
User โ†’ Post1-to-manyCreator writes many posts
User โ†’ SubscriptionMany-to-manyReaders subscribe to creators
Post โ†’ Comment1-to-manyPost has multiple comments
Post โ†’ TagMany-to-manyPosts have multiple tags
Subscription โ†’ Payment1-to-manyEach subscription has many payments
Post โ†’ EmailQueue1-to-manyEach post triggers multiple emails

Indexing & Optimization

TableIndexed ColumnsPurpose
UseremailFast login lookups
Postslug, author_idQuick post retrieval
Subscriptionreader_id, creator_idFast subscription checks
Paymentstripe_txn_idPayment reconciliation
EmailQueuestatusQueue processing efficiency

Additional Optimizations:

  • Use partial indexes for active subscriptions only.
  • Add foreign key constraints for referential integrity.
  • Enable caching for popular posts (via Redis).

Data Flow Example โ€“ โ€œUser Subscribes to Creatorโ€

[User clicks Subscribe]
        โ”‚
        โ–ผ
Frontend โ†’ Backend (Subscription Service)
        โ”‚
        โ–ผ
Stripe Checkout โ†’ Payment Verified
        โ”‚
        โ–ผ
Backend updates:
- Create subscription record
- Log payment
- Send email confirmation

Reflection

A strong schema is like a well-organized library โ€“ every book (post), reader, and transaction has its place.

This database design ensures:

  • Fast retrieval of posts and subcriptions,
  • Consistent data across users and payments.
  • Extensibility for future modules (plugins, AI summaries, comments, etc.)

โ€œDatabase is like long-term memory โ€“ design it like you will read from it for years.โ€

Buy Me A Coffee

Leave a comment

Your experience on this site will be improved by allowing cookies Cookie Policy