Designing Follow Systems Beyond CRUD

Dec 05, 20254 mins read

A follow system looks deceptively simple.

At first glance, it’s just:

  • Follow a user
  • Unfollow a user
  • Show follower and following counts

But once real users enter the system, a follow feature quickly evolves from basic CRUD into a distributed systems problem.

Designing this correctly requires thinking about scale, consistency, and user experience - not just database operations.

Why Follow Systems Are Not Just CRUD

CRUD assumes:

  • Independent operations
  • Simple data flows
  • Minimal side effects

A follow action violates all three.

When one user follows another:

  • Two users’ states change
  • Feeds may need to update
  • Notifications may be triggered
  • Counts must stay accurate

This single action can ripple through multiple parts of the system.

Core Data Model

A typical follow system uses a join table:

follows
-------
follower_id
following_id
created_at

With constraints:

  • (follower_id, following_id) must be unique
  • A user cannot follow themselves

This table becomes hot very quickly in large systems. Indexes and constraints are not optional - they are fundamental.

Handling Idempotency

One of the most common issues in follow systems is duplicate requests.

Users may:

  • Double-click the follow button
  • Retry requests due to network issues

Without idempotency:

  • Follower counts inflate
  • Data becomes inconsistent

The solution is simple but essential:

  • Enforce a unique constraint at the database level
  • Treat duplicate follow requests as no-ops

Idempotency turns repeated actions into safe operations.

Consistency vs Performance

A key design decision is how follower counts are handled.

Option 1: Calculate Counts Dynamically

  • Always accurate
  • Expensive at scale

Option 2: Store Counts Separately

  • Fast reads
  • Requires careful updates

Most production systems choose a hybrid approach:

  • Store counts for fast reads
  • Periodically reconcile for correctness

This trade-off is unavoidable in large-scale systems.

Feeds and Fan-Out Strategy

Follow systems directly impact feed generation. Two common approaches exist:

Fan-Out on Write

  • Push new posts to followers’ feeds
  • Fast reads
  • Expensive writes

Fan-Out on Read

  • Generate feed at request time
  • Cheaper writes
  • Slower reads

The right choice depends on user behavior, read/write ratios, and infrastructure constraints.

Edge Cases That Matter

Some edge cases are easy to overlook:

  • Blocking a user
  • Private accounts (request vs. follow)
  • Deactivated users
  • Race conditions during follow/unfollow

Ignoring these early leads to painful refactors later. Good backend design anticipates these scenarios upfront.

Designing for Scale From Day One

A follow system will almost always grow. Designing with scale in mind means:

  • Proper indexing
  • Clear data ownership
  • Idempotent APIs
  • Thoughtful feed architecture

Even small applications benefit from these decisions early.

Final Thoughts

Follow systems are a perfect example of how backend engineering goes beyond CRUD. They force you to think in terms of:

  • System behavior
  • Failure scenarios
  • Trade-offs at scale

Good backend systems aren’t defined by how they work on day one, but by how well they hold up as usage grows.