Tracking Unique API Visitors with Redis Sets
Learn to track unique visitors to your API using Redis Sets. Master SADD, SCARD, and DEL commands to build efficient, real-time analytics for your application.

Previously in this course, we explored Set Operations: Intersection and Union in Redis, where we learned how to compare groups of data. Now, we’ll apply those concepts to a practical challenge: tracking unique API visitors.
In web development, "unique visitors" refers to the number of distinct users—typically identified by IP address, session ID, or user ID—that interact with your service over a specific period. Storing this in a traditional relational database often requires heavy SELECT DISTINCT queries that grow slower as your traffic scales. Redis Sets provide a high-performance alternative because they are designed by definition to hold only unique members.
Tracking Unique Visitors with Redis Sets
A Redis Set is an unordered collection of strings. The core property of a Set is that it automatically handles deduplication; if you try to add the same member twice, Redis simply ignores the second attempt. This makes it the perfect data structure for counting unique entities.
When we track visitors, we typically use three primary commands:
SADD: Adds a new visitor ID to the set.SCARD: Returns the cardinality (the count) of the set.DEL: Clears the set once the reporting period (e.g., a 24-hour window) ends.
Worked Example: Visitor Analytics Service
Let’s integrate this into our project. We will create a simple service that tracks unique visitor IDs for a specific API endpoint.
JAVASCRIPTconst redis = require(CE9178">'redis'); const client = redis.createClient(); async function trackVisitor(endpoint, visitorId) { // We use a namespaced key: visitors:endpoint_name const key = CE9178">`visitors:${endpoint}`; // SADD returns 1 if the element was added, 0 if it was already present await client.sAdd(key, visitorId); } async function getUniqueVisitorCount(endpoint) { const key = CE9178">`visitors:${endpoint}`; // SCARD returns the total number of unique elements in the set const count = await client.sCard(key); return count; } async function resetDailyVisitors(endpoint) { const key = CE9178">`visitors:${endpoint}`; await client.del(key); }
In this implementation, every time a request hits your API, you call trackVisitor. Because Redis keeps this data in memory, the overhead of checking for uniqueness is negligible, even at high traffic volumes. Unlike Standardizing Response Envelopes: Clean API Design Patterns, where we focus on the structure of data outgoing to the client, here we focus on the efficiency of data ingestion internal to our backend.
Hands-on Exercise
- Launch your
redis-cli. - Simulate three visits to a home page from two users (e.g., user "Alice" visits twice, "Bob" visits once).
SADD visitors:home "alice"SADD visitors:home "bob"SADD visitors:home "alice"
- Run
SCARD visitors:home. You should see2. - Remove the tracking data using
DEL visitors:home.
Common Pitfalls
- Memory Growth: Since Sets store every unique ID, if your visitor count grows into the millions, the memory usage will climb. If you only need an approximate count for massive scale, consider looking into Redis HyperLogLogs in the future, which trade a tiny amount of accuracy for massive memory savings.
- Forgetting to Expire: If you don't use
DELor set an expiration (usingEXPIREas seen in Implementing Expiration and TTL in Redis for Data Management), your memory usage will grow indefinitely. - Key Collisions: Always use a consistent naming convention. If you are tracking visitors for multiple endpoints, ensure your keys are namespaced (e.g.,
visitors:api_v1:loginvsvisitors:api_v1:signup) as discussed in Mastering Key Naming Conventions: Redis Best Practices.
Frequently Asked Questions
Does SADD slow down as the set grows?
No. Adding a member to a set has a time complexity of O(1), meaning it takes the same amount of time regardless of whether you have 10 or 1,000,000 members.
Can I store objects in a Set? Redis Sets only store strings. If you need to track unique users by their full profile object, store a unique identifier (like a UUID or username) in the set, and keep the full object in a separate Hash.
What happens if I call SADD with the same ID?
Redis simply returns 0 and does nothing, ensuring the set size remains accurate.
Recap
We’ve successfully moved from caching responses to tracking real-time user metrics. By leveraging the inherent deduplication of Redis Sets, we can count unique visitors with O(1) performance using SADD and SCARD. Remember to manage your memory by cleaning up keys once your analytics window closes.
Up next: We will dive into Atomic Operations, ensuring that even under high concurrency, our visitor counts remain perfectly accurate.
Work with me

Laravel REST API Development
Clean, secure, well-documented Laravel REST APIs — the backend engine for your app, mobile client, or SaaS. Built by an API specialist.

FilamentPHP Admin Panel & Dashboard Development
A powerful admin panel for your Laravel app — built with FilamentPHP so you can manage everything without touching the database.


