redis_smembersReturns all members of a set — unbounded on large sets
SMEMBERS returns every member of a Redis set in a single response. It is O(N) where N is the set cardinality. Sets that grow unboundedly — user IDs, tags, permission lists, follower sets — will cause SMEMBERS to transfer increasing amounts of data over time. A set with 100,000 members returns all of them in one call.
Common Causes
- —Membership stores that grow as users interact with the application
- —Tag or category indexes without size bounds
- —Permission or role sets that accumulate over time
- —Social graph edges (followers, friends) stored as sets
How to Fix
- 1.Use SSCAN with a cursor for incremental iteration on large sets
- 2.Use SRANDMEMBER with a count for sampling without full retrieval
- 3.Use SISMEMBER or SMISMEMBER to check specific membership without fetching all
- 4.Cap set size at write time — SADD + SCARD check or use a sorted set with ZREMRANGEBYRANK
Example
typescript
// BAD — returns all 50,000 follower IDs
const followers = await redis.smembers(`followers:${userId}`);
// GOOD — check membership without fetching the whole set
const isFollowing = await redis.sismember(`followers:${userId}`, targetId);
// GOOD — check multiple memberships at once
const [followsA, followsB] = await redis.smismember(`followers:${userId}`, userA, userB);
// GOOD — cursor-based iteration when you need to process all members
async function processFollowers(redis: Redis, userId: string) {
let cursor = '0';
do {
const [next, members] = await redis.sscan(`followers:${userId}`, cursor, 'COUNT', 200);
cursor = next;
await processPage(members);
} while (cursor !== '0');
}
// GOOD — random sample for feeds without full retrieval
const sampleFollowers = await redis.srandmember(`followers:${userId}`, 50);
// GOOD — bounded sets using sorted set + cleanup
await redis.zadd(`recent:viewers:${postId}`, Date.now(), userId);
await redis.zremrangebyrank(`recent:viewers:${postId}`, 0, -1001); // keep latest 1000Use SISMEMBER for membership checks
If you only need to know whether a specific value is in the set, SISMEMBER is O(1) and returns immediately. Never call SMEMBERS just to check if one value is present.