We use analytics cookies.We use cookies to analyze site traffic and improve your experience.
Loading...
3 system design questions lean on this idea. Each walks through the full answer.
System Design Masterclass · Database Fundamentals
Free preview: the first 2 parts of this 9-part lesson.
Already bought the course? Sign in to read the whole lesson.
this lesson is part of
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design courseread the rest of this lesson in
System Design Masterclass
Unlock this lesson and the 751 other paid lessons
$25 once, by PayPal
See the System Design coursein Database Fundamentals
This lesson is part of the full System Design Masterclass. Unlock it along with 769 other lessons for a one-time payment.
One-time payment by card or PayPal
Get Lifetime AccessOne-time payment: UPI, card or netbanking
Get Lifetime Access18 Foundation lessons are free, no payment needed. Try them now
It is easy and good
“It is really nice and good Please join the course”
A learning platform, similar to this one, had 500,000 registered users. The database handled everything: user signups, lesson progress writes, quiz scoring, AND the heavy read queries for the dashboard, leaderboard, course catalog, and roadmap.
The write load was manageable, maybe 200 writes per second during peak. But reads were crushing. The leaderboard page ran an expensive aggregation query. The course catalog page queried lessons with filters and pagination. The dashboard pulled progress data with multiple JOINs. During peak hours. 6 PM to 10 PM, the database CPU sat at 95%. Read queries started queuing behind write transactions. Everything got slower.
The instinct is to throw a bigger server at the problem. Vertical scaling. They went from 4 cores to 8 cores. Bought themselves three months. Then from 8 to 16. Bought two more months. This doesn't end well, eventually there's no bigger server to buy, and each upgrade costs double.
The real fix: stop making one database do everything. Writes go to the primary. Reads get distributed across replicas. This is read , and it's how every database-heavy platform scales beyond a single server.
The concept is straightforward. You have one primary database (also called "master" or "leader") that handles all writes. You create one or more replicas (also called "followers" or "standbys") that receive copies of the data from the primary and handle read queries.
The process:
From the application's perspective, you route queries based on type:
// Simplified connection routing
import { neon } from '@neondatabase/serverless';
// Primary, for writes
const primary = neon(process.env.DATABASE_URL!);
// Replica, for reads
const replica = neon(process.env.DATABASE_READ_REPLICA_URL!);
// Write: always primary
await primary`INSERT INTO lesson_progress (user_id, lesson_id, completed) VALUES (${userId}, ${lessonId}, true)`;
// Read: use replica
const progress = await replica`SELECT * FROM lesson_progress WHERE user_id = ${userId}`;