Scaling View Tracking with Redis Counters in Social Video App

Tracking user engagement like views and replays is critical for content ranking, personalization, and analytics β€” but doing it in real time can overwhelm your database. That's where Redis shines.

In this post, you'll learn how to build scalable view and replay counters using Redis, and flush them periodically into your database.


🧱 Why Use Redis?

Traditional view tracking can easily create millions of rows β€” especially if you log every view. That’s overkill unless you need granular logs. Instead, use Redis counters for:

  • Fast, in-memory incrementing

  • Throttle-proof updates (with TTLs)

  • Easy batching and flushing to DB

  • Scalable with low overhead


πŸ”§ Key Design

Use simple, structured Redis keys:

view:<media_id>         β†’ Total views
replay:<media_id>       β†’ Total replays
user_view:<user_id>:<media_id> β†’ To prevent abuse (with TTL)

Example

view:4382 β†’ 129
replay:4382 β†’ 27
user_view:982:4382 β†’ true

πŸ“ˆ Incrementing Counters (Laravel Example)

$mediaId = 4382;
$userId = 982;

// Avoid duplicate views within 30 minutes
if (!Redis::get("user_view:$userId:$mediaId")) {
    Redis::incr("view:$mediaId");
    Redis::setex("user_view:$userId:$mediaId", 1800, true); // 30 mins TTL
}

// On replay
Redis::incr("replay:$mediaId");

You can extend this logic to support anonymous users using session_id or IP-based tracking.


πŸ—ƒοΈ Flushing Redis to Database

Use a scheduled job (e.g., every 5–15 minutes) to flush counters:

$keys = Redis::keys('view:*');

foreach ($keys as $key) {
    $mediaId = explode(':', $key)[1];
    $views = Redis::get($key);
    $replays = Redis::get("replay:$mediaId") ?? 0;

    DB::table('media')->where('id', $mediaId)->update([
        'views_count' => DB::raw("views_count + $views"),
        'replay_count' => DB::raw("replay_count + $replays")
    ]);

    Redis::del("view:$mediaId");
    Redis::del("replay:$mediaId");
}

This way, your main database only sees updates every few minutes, not every few milliseconds.


🧠 Bonus: Querying Redis Keys

# All view keys
KEYS view:*

# Safer in production
SCAN 0 MATCH view:* COUNT 100

# Get counter value
GET view:4382

βš™οΈ Final Notes

  • βœ… Start with Redis + DB flush

  • πŸ” Add message queue (e.g., BullMQ, Sidekiq) if scale grows

  • πŸ“Š Use Redis Streams or analytics DB (e.g., ClickHouse) for full logs later

  • πŸ”’ Protect routes with throttling to avoid abuse


πŸ“Œ Conclusion

Redis counters give you a clean, scalable foundation to track video engagement like views and replays without crushing your database. This approach is perfect for apps where speed and simplicity matter.

0
Subscribe to my newsletter

Read articles from Mohammad Shabaz Moosa directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Mohammad Shabaz Moosa
Mohammad Shabaz Moosa