Compose Redis Sets with union, intersection, and difference while making cardinality, Cluster locality, and freshness cost explicit.

SUNION/SINTER/SDIFF and Set Algebra for Tags, Audiences, and Permissions

Choose hashes, Redis JSON, or many keys from structure, update/query patterns, expiration granularity, memory/cardinality, indexing, ACL boundaries, and migration evidence.

Intermediate135–170 minutesSet algebra + Cluster-locality labRedis Open Source 8.10.1Free/local-firstLast reviewed: September 6, 2026

Learning outcomes

AtlasMart wants audiences such as “VIP customers who opted into email but are not suppressed” and permission sets such as “operators allowed for store 42.” Redis Set algebra can compute these relations directly, but the output size and number/cardinality of input sets determine work.

01

Compute SUNION, SINTER, and SDIFF and interpret missing-key behavior.

02

Reason from documented command complexity instead of assuming all Set operations are O(1).

03

Use cardinality-only variants when the question asks only “how many?” and verify server version.

04

Design Cluster hash tags for same-slot multi-key algebra without creating accidental hot-slot concentration.

05

Use set-derived permissions/audiences with explicit freshness, source-of-truth, and rollback policy.

Exact lab baseline

All Chapter 05 mandatory labs reuse the disposable Chapter 01 environment: Redis Open Source 8.10.1 from Docker Official Image redis:8.10.1, container atlasmart-redis-ch01, standalone topology, host publication 127.0.0.1:6379, TLS disabled only because traffic stays on loopback, default ACL user disabled, named ACL users atlasmart-app and academy-admin, logical database 0, AOF with appendfsync everysec plus RDB snapshots, persistent /data volume, and no explicit Redis maxmemory limit or eviction policy. The application ACL is restricted to ~atlasmart:* and normal read/write/connection categories. The primary interface is the redis-cli shipped in the same 8.10.1 image, so server and CLI versions stay aligned. Mandatory examples use only bounded synthetic keys under atlasmart:ch05:*.

1. Union, intersection, and difference answer different questions

SUNION returns members present in any input set. SINTER returns only members present in every input set. SDIFF A B C is directional: it returns members of A that are absent from B and C. Missing keys are treated as empty sets, which changes intersection and difference in predictable ways.

redis-cli · AtlasMart audience algebra
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app DEL atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:email atlasmart:ch05:{fall}:suppresseddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SADD atlasmart:ch05:{fall}:vip c1 c2 c3 c4docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SADD atlasmart:ch05:{fall}:email c2 c3 c4 c5docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SADD atlasmart:ch05:{fall}:suppressed c4docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SUNION atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:emaildocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SINTER atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:emaildocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SDIFF atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:suppressed

Set reply ordering is not a stable business ordering. Compare membership, not display sequence.

2. Cost follows cardinality, not command-name simplicity

Current Redis documentation classifies these algebra commands as slow relative to constant-time membership primitives. SUNION and SDIFF are O(N) in the total elements considered. SINTER is O(N×M) worst case where N is the cardinality of the smallest set and M is the number of sets. Returning a huge result also costs memory, serialization, network bandwidth, and client decoding.

redis-cli · measure inputs before algebra
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SCARD atlasmart:ch05:{fall}:vipdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SCARD atlasmart:ch05:{fall}:emaildocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SCARD atlasmart:ch05:{fall}:suppresseddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app MEMORY USAGE atlasmart:ch05:{fall}:vip

Do not invent a universal “safe cardinality.” Record real cardinalities, payload sizes, p50/p95/p99 latency, concurrency, and Cluster topology for your workload.

3. Ask for cardinality when you do not need the members

SINTERCARD has existed since Redis 7.0 and returns only intersection cardinality. Redis 8.10 adds SUNIONCARD and SDIFFCARD. These avoid transferring the full result when the business question is “how many?”, though the server still must perform the relevant set computation.

redis-cli · version-aware cardinality-only operations
docker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin COMMAND INFO SINTERCARD SUNIONCARD SDIFFCARDdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SINTERCARD 2 atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:emaildocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SUNIONCARD 2 atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:emaildocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SDIFFCARD 2 atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:suppressed

The two 8.10 commands are version-sensitive extensions. Capability-check them before depending on a managed/proxy/older server.

4. Store variants materialize a derived Set—and create freshness work

SINTERSTORE, SUNIONSTORE, and SDIFFSTORE write the derived result to a destination key. This can move repeated computation off a read path, but it creates a materialized view whose refresh, invalidation, TTL, ACL, and rollback must be designed.

redis-cli · materialize a target audience
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SINTERSTORE atlasmart:ch05:{fall}:eligible atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:emaildocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SREM atlasmart:ch05:{fall}:eligible c4docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SMEMBERS atlasmart:ch05:{fall}:eligibledocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app EXPIRE atlasmart:ch05:{fall}:eligible 600

The manual SREM c4 illustrates why ad hoc post-processing is fragile. A better design encodes the suppression relation in a reproducible computation such as an intersection followed by difference, or computes it in a transaction/function/application pipeline with a versioned source snapshot.

5. Cluster: multi-key algebra requires key locality

Redis Cluster partitions keys into 16,384 hash slots. Multi-key operations generally require the participating keys to be in the same slot. Hash tags—the substring inside {...}—let related keys intentionally share a slot. The lab keys use {fall} for that reason.

Do not tag an entire global tenant or every campaign with one constant just to silence CROSSSLOT; that can concentrate traffic and memory into one slot. Choose a locality boundary that matches the operation and expected scale, then measure slot distribution.

6. Permissions: fast membership is not the whole authorization system

Sets are attractive for roles and permissions because SISMEMBER is fast and algebra is expressive. But a stale Redis permission set can grant access after the source policy revoked it. Treat Redis as a derived authorization cache only when versioning/invalidation, fail-closed behavior, audit evidence, and source-of-truth reconciliation are explicit.

redis-cli · permission relation example
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app DEL atlasmart:ch05:{store42}:role:manager atlasmart:ch05:{store42}:perm:refunddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SADD atlasmart:ch05:{store42}:role:manager user:a user:bdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SADD atlasmart:ch05:{store42}:perm:refund user:b user:cdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SINTER atlasmart:ch05:{store42}:role:manager atlasmart:ch05:{store42}:perm:refund

The intersection answers the data question on the current Redis state; it does not prove that state is current enough to authorize a real refund.

7. Deliberately wrong: huge synchronous algebra on a hot request path

A request handler that executes SINTER across several million-member sets and returns all matches can monopolize server execution time and generate a massive response. The syntax is short; the work is not.

Safe failure model

Do not generate million-member sets in this course lab. Use small fixtures to prove semantics, then use cardinality and staging benchmarks in a disposable performance environment to establish production limits.

redis-cli · small correctness fixture only
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SINTER atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:emaildocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SINTERCARD 2 atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:email LIMIT 1

Repair options include cardinality-only queries, precomputed/materialized audiences, background recomputation, smaller partitioned sets, or a different analytical system when the workload is fundamentally batch/large-scale.

8. Hands-on lab: audience decision record

Compute “VIP ∩ email − suppressed” and verify every intermediate cardinality.

redis-cli · audience evidence card
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SINTERSTORE atlasmart:ch05:{fall}:vip-email atlasmart:ch05:{fall}:vip atlasmart:ch05:{fall}:emaildocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SDIFFSTORE atlasmart:ch05:{fall}:send atlasmart:ch05:{fall}:vip-email atlasmart:ch05:{fall}:suppresseddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SCARD atlasmart:ch05:{fall}:senddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app SMEMBERS atlasmart:ch05:{fall}:senddocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app MEMORY USAGE atlasmart:ch05:{fall}:send

Record source cardinalities, result cardinality, hash-tag locality assumption, result TTL policy, and how the derived audience will be invalidated if a source Set changes.

9. Production judgment

Set algebra is excellent for bounded, key-local membership relations. Keep large synchronous results off latency-sensitive paths unless measurements justify them. In Cluster, design slot locality deliberately. For authorization and regulated audiences, preserve an authoritative source and an auditable refresh/version story. When the relation needs ranked output, time ordering, or durable change history, another structure may be more appropriate.

10. Summary and next step

Union, intersection, and difference make Sets composable, but cardinality determines real cost and Cluster determines where multi-key operations are legal. The final lesson turns these mechanics into a structure-selection decision across Lists, Sets, Streams, and Sorted Sets.

Check your understanding

  1. What happens to SINTER when one input key does not exist?
  2. Why can SUNION be expensive even though SADD is O(1) per member?
  3. When should you prefer SINTERCARD over SINTER?
  4. Why do {hash tags} matter in Redis Cluster?
  5. Why should a Redis permission Set usually have a source-of-truth/versioning story?
Review the answers

A missing Set is treated as empty, so the intersection is empty.

SUNION must examine members across all inputs and may return a large result; operation complexity differs from membership insertion.

When you need only the count, avoiding the full member reply reduces network/client result cost.

They force related keys into the same hash slot so multi-key operations can be legal; poor tag design can create hotspots.

Cached permissions can become stale after policy changes; correctness and auditability require freshness and reconciliation guarantees.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.