Skip to main content

Command Palette

Search for a command to run...

The Day My “Simple” Database Design Collapsed Under Real Users

Updated
6 min read
The Day My “Simple” Database Design Collapsed Under Real Users
R

I am a full-stack developer (currently working with cognizant) who is passionate about web development and creating digital products with innovative solutions.

I hold 6+ years of experience in development, understanding clients' unique needs, and delivering quality code. I've honed my coding skills over these years through both my professional exposure and self-study. Have worked with teams that have used agile development methodology.

I am someone who likes to keep acquiring new skills and capabilities. And when I am not a web developer, I enjoy reading, writing and running.

My interests include:

  • Exploring new ideas
  • Learning about future tech & products
  • Finding user-friendly solutions to tech-related problems
  • Sharing my knowledge with close acquaintances

It started with confidence.

I had built what I thought was a clean schema for a social media app. One table. Everything inside it.

Users, posts, likes, comments—just neatly packed together.

It worked perfectly…

Until it didn’t.

Queries slowed down. Data duplicated. Relationships got messy. And the worst part?

I couldn’t even answer a simple question like:

“Who liked this photo?”

Without writing a monster query that felt like decoding ancient scripts.

That’s when I realized:

Good database design isn’t about storing data. It’s about modeling reality correctly.


The Roadmap

In this guide, we are going to explore 6 key concepts to help you master relational database design using a real-world social media schema:

  1. Why normalization matters

  2. Breaking systems into entities

  3. One-to-many relationships (users → photos, comments)

  4. Many-to-many relationships (likes, tags)

  5. Self-referencing relationships (follows)

  6. Production insights (scaling, performance, real-world systems)


1. Why You Can’t Store Everything in One Table

Let’s start with the mistake I made.

I tried this:

users + photos + comments + likes + tags → ONE TABLE

It felt efficient.

It was not.

Why It Matters (Production Reality)

When everything lives in one table:

  • Data gets duplicated

  • Updates become inconsistent

  • Queries become slow

  • Relationships become unclear

This is exactly what normalization solves.

Analogy: A Messy Warehouse

Imagine a warehouse where:

  • Clothes

  • Electronics

  • Food

…are all dumped in one room.

Now try finding something.

That’s your database without normalization.

Debug Scenario

What happens if this fails?

  • Same user stored multiple times

  • Updates don’t sync

  • Reports become inaccurate

Senior Dev Perspective 💡

If your table starts feeling like a “dumping ground,” you’ve already lost.


2. Entities — Modeling the Real World Correctly

Real systems don’t think in tables.

They think in entities.

From the schema:

users
photos
comments
likes
follows
tags
photo_tags

Each represents a real-world concept.

Why It Matters

Separating entities allows:

  • Clean relationships

  • Scalable design

  • Efficient queries

Analogy: A City

Think of a social network as a city:

  • Users → citizens

  • Photos → billboards

  • Comments → conversations

  • Likes → approvals

  • Follows → friendships

Each has its own place.

Debug Scenario

What happens if this fails?

  • Mixing entities leads to confusion

  • Relationships break

  • Data becomes unreliable

Senior Dev Perspective 💡

Design your schema like you're modeling reality—not just writing SQL.


3. One-to-Many Relationships — The Backbone

Example: Users → Photos

1 user → many photos
CREATE TABLE photos (
    id INTEGER AUTO_INCREMENT PRIMARY KEY,
    image_url VARCHAR(255) NOT NULL,
    user_id INTEGER NOT NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    FOREIGN KEY(user_id) REFERENCES users(id)
);

Why It Matters

This relationship ensures:

  • Each photo belongs to a user

  • Data stays connected

  • Queries remain simple

Analogy: Author & Books

One author writes many books.

But each book has one author.

Same idea.

Debug Scenario

What happens if this fails?

  • Photos without owners

  • Broken references

  • Orphaned data

Senior Dev Perspective 💡

Foreign keys are not optional—they’re your safety net.


4. Many-to-Many Relationships — Where Things Get Interesting

Example: Likes

A user can like many photos.
A photo can be liked by many users.

Solution:

CREATE TABLE likes (
    user_id INTEGER NOT NULL,
    photo_id INTEGER NOT NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    FOREIGN KEY(user_id) REFERENCES users(id),
    FOREIGN KEY(photo_id) REFERENCES photos(id),
    PRIMARY KEY(user_id, photo_id)
);

Why It Matters

This prevents:

  • Duplicate likes

  • Data inconsistency

Analogy: Students & Courses

  • One student → many courses

  • One course → many students

You need a middle table.

Debug Scenario

What happens if this fails?

  • Duplicate likes

  • Inflated counts

  • Broken analytics

Senior Dev Perspective 💡

Junction tables are where clean design meets real-world complexity.


5. Self-Referencing Relationships — Modeling Human Behavior

Example: Follows

CREATE TABLE follows (
    follower_id INTEGER NOT NULL,
    followee_id INTEGER NOT NULL,
    created_at TIMESTAMP DEFAULT NOW(),
    FOREIGN KEY(follower_id) REFERENCES users(id),
    FOREIGN KEY(followee_id) REFERENCES users(id),
    PRIMARY KEY(follower_id, followee_id)
);

Why It Matters

Users relate to other users.

This is different from normal relationships.

Analogy: Friendships

In real life:

  • You follow someone

  • Someone follows you

Same table. Different roles.

Debug Scenario

What happens if this fails?

  • Invalid relationships

  • Duplicate follows

  • Logical inconsistencies

Senior Dev Perspective 💡

Self-referencing tables are simple to write—but tricky to reason about.


6. Tags & Flexibility — Designing for Growth

Example: Tags + Photo Tags

CREATE TABLE tags (
  id INTEGER AUTO_INCREMENT PRIMARY KEY,
  tag_name VARCHAR(255) UNIQUE,
  created_at TIMESTAMP DEFAULT NOW()
);
CREATE TABLE photo_tags (
    photo_id INTEGER NOT NULL,
    tag_id INTEGER NOT NULL,
    FOREIGN KEY(photo_id) REFERENCES photos(id),
    FOREIGN KEY(tag_id) REFERENCES tags(id),
    PRIMARY KEY(photo_id, tag_id)
);

Why It Matters

Tags allow:

  • Flexible categorization

  • Search features

  • Discoverability

Analogy: Labels on Files

Instead of storing files in one folder:

  • Add labels

  • Filter easily

Debug Scenario

What happens if this fails?

  • Duplicate tags

  • Poor search

  • Bad user experience

Senior Dev Perspective 💡

Design for features you don’t have yet—tags are future-proofing.


7. Performance & Production Reality — Where Theory Meets Scale

From real-world systems:

What Changes in Production?

You don’t just have tables.

You have:

millions of rows
high traffic
complex queries

Key Techniques

  • Indexes on foreign keys

  • Read replicas

  • Caching (Redis)

  • CDN for images

  • Async queues

Critical Insight

Photos are NOT stored in DB.

Only this is stored:

image_url

Actual images → S3 / CDN

Analogy: Library System

The database is a catalog.

The actual books? Stored elsewhere.

Senior Dev Perspective 💡

Databases store references—not heavy assets.


8. The Real Skill — Asking Better Questions

Example Query

SELECT *
FROM users
ORDER BY created_at
LIMIT 5;

This finds:

5 oldest users

Why It Matters

Good schema design makes queries:

  • Simple

  • Fast

  • Understandable

Bad schema?

Everything becomes painful.


The Bridge (Back to That Broken Design)

That messy one-table design I started with?

It didn’t fail because SQL is hard.

It failed because I didn’t understand how systems scale.

This schema taught me something deeper:

Clean database design isn’t about tables—it’s about thinking in relationships.

And once you see it…

You can’t unsee it.