Bitmap Patterns

Store millions of boolean flags in minimal memory using Redis bitmaps—1 bit per flag with O(1) access, plus fast aggregate operations across entire datasets.

A Redis bitmap is a string where each bit represents a boolean value. With SETBIT and GETBIT, you can address individual bits by offset. One megabyte stores 8 million flags. Combined with BITCOUNT and BITOP, bitmaps enable powerful analytics on binary state.

Basic Operations

Set a bit (user 1000 is active):

SETBIT users:active 1000 1

Get a bit:

GETBIT users:active 1000
# Returns: 1

Count all set bits:

BITCOUNT users:active
# Returns: number of active users

Pattern: Daily Active Users

Track which users were active each day:

# User 12345 visited today
SETBIT dau:2024-01-30 12345 1

# Count daily active users
BITCOUNT dau:2024-01-30

# Check if specific user was active
GETBIT dau:2024-01-30 12345

Memory: 1 million users = 125 KB per day.

Weekly/Monthly Active Users

Combine daily bitmaps with BITOP:

# Users active ANY day this week (union)
BITOP OR wau:2024-W05 dau:2024-01-28 dau:2024-01-29 dau:2024-01-30 ...

# Users active EVERY day this week (intersection)
BITOP AND wau:2024-W05:daily dau:2024-01-28 dau:2024-01-29 ...

BITCOUNT wau:2024-W05

Pattern: Feature Flags per User

Track which features each user has enabled:

# Bit positions represent features
# 0 = dark_mode, 1 = notifications, 2 = beta_features, ...

# Enable dark mode for user 5000
SETBIT user:5000:features 0 1

# Enable beta features
SETBIT user:5000:features 2 1

# Check if notifications enabled
GETBIT user:5000:features 1

Bulk Feature Check

Get all feature bits at once with GETEX (or GET) and parse client-side:

GET user:5000:features
# Returns binary string, decode to check multiple features

Pattern: Online Status

Track online users with automatic expiration:

# User comes online
SETBIT online:users 12345 1

# User goes offline
SETBIT online:users 12345 0

# Count online users
BITCOUNT online:users

For millions of users, this uses far less memory than storing individual keys.

Time-Windowed Online

Use time-bucketed keys for "active in last 5 minutes":

# Bucket by minute
SETBIT online:minute:1706648400 12345 1
EXPIRE online:minute:1706648400 300

# Active in any of last 5 minutes
BITOP OR online:recent online:minute:1706648400 online:minute:1706648460 ...

Pattern: Bloom Filter Alternative

For simple membership testing without external modules:

# Multiple hash functions map item to bit positions
pos1 = hash1(item) % bitmap_size
pos2 = hash2(item) % bitmap_size
pos3 = hash3(item) % bitmap_size

# Add item
SETBIT bloom:filter pos1 1
SETBIT bloom:filter pos2 1
SETBIT bloom:filter pos3 1

# Check membership (all bits must be set)
GETBIT bloom:filter pos1  # AND
GETBIT bloom:filter pos2  # AND
GETBIT bloom:filter pos3

If any returns 0, item is definitely not in set. If all return 1, item is probably in set (false positives possible).

Note: For production bloom filters, use Redis Stack's BF.* commands which handle sizing and hash functions automatically.

Pattern: User Cohort Analysis

Analyze user segments:

# Track user attributes as bitmaps
SETBIT users:premium 12345 1
SETBIT users:mobile 12345 1
SETBIT users:country:us 12345 1

# Premium mobile users in US
BITOP AND cohort:premium_mobile_us users:premium users:mobile users:country:us
BITCOUNT cohort:premium_mobile_us

# Premium users NOT on mobile
BITOP NOT users:not_mobile users:mobile
BITOP AND cohort:premium_desktop users:premium users:not_mobile
BITCOUNT cohort:premium_desktop

Pattern: Rate Limiting with Bitmaps

Track requests per second with bit-level granularity:

# One bit per millisecond, offset = ms within second
SETBIT ratelimit:user:123:1706648400 150 1  # Request at 150ms

# Count requests in this second
BITCOUNT ratelimit:user:123:1706648400

# Expire after 2 seconds
EXPIRE ratelimit:user:123:1706648400 2

Memory: 1000 bits (125 bytes) per user per second.

BITFIELD: Advanced Bit Manipulation

BITFIELD provides atomic read-modify operations on arbitrary bit ranges:

# Store 8-bit counter at offset 0
BITFIELD counters SET u8 0 100

# Increment with overflow handling
BITFIELD counters INCRBY u8 0 1 OVERFLOW SAT

# Multiple operations atomically
BITFIELD mykey SET u8 0 200 INCRBY u8 100 1 GET u4 0

Packed Counters

Store multiple small counters in one key:

# 4 8-bit counters in 32 bits
BITFIELD user:123:stats SET u8 0 50    # Counter 0 = 50
BITFIELD user:123:stats SET u8 8 100   # Counter 1 = 100
BITFIELD user:123:stats SET u8 16 25   # Counter 2 = 25
BITFIELD user:123:stats SET u8 24 75   # Counter 3 = 75

# Read all at once
BITFIELD user:123:stats GET u8 0 GET u8 8 GET u8 16 GET u8 24

BITPOS: Finding Set/Unset Bits

Find the first set or unset bit:

# First active user (first 1 bit)
BITPOS users:active 1

# First inactive user ID (first 0 bit)
BITPOS users:active 0

# First set bit in range (bytes 100-200)
BITPOS users:active 1 100 200

Memory Efficiency

Users Bitmap Size Equivalent SET
1 million 125 KB ~50 MB
10 million 1.25 MB ~500 MB
100 million 12.5 MB ~5 GB

Bitmaps are ~400x more memory-efficient than storing user IDs in a Set.

Limitations

Sparse Data

Bitmaps allocate memory for the highest offset used. If user IDs are sparse (e.g., UUIDs mapped to integers), memory is wasted:

SETBIT users:active 999999999 1  # Allocates ~125 MB!

Solutions: - Use dense, sequential IDs - Hash UUIDs to a bounded range (accept collisions) - Use Sets for sparse data instead

ID Space

User IDs must be non-negative integers. Map other identifiers:

# If using UUIDs, maintain a mapping
INCR user:id:counter                        # Get next integer ID
SET user:uuid:abc123 {integer_id}           # Map UUID to integer
SETBIT users:active {integer_id} 1          # Use integer in bitmap

Bit Operations Complexity

BITOP is O(N) where N is the size of the longest input string. For huge bitmaps, operations can be slow:

# May be slow for 100M+ users
BITOP AND result bitmap1 bitmap2 bitmap3

Consider sharding large bitmaps by ID range.

Summary

Use Case Commands Memory
User presence SETBIT, GETBIT 1 bit/user
Daily active SETBIT + BITCOUNT 125KB/1M users
Cohort intersection BITOP AND Same as input
Feature flags SETBIT per feature N bits/user
Packed counters BITFIELD Configurable

← Back to Index | Markdown source