iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Hashes

A Redis hash is a string-keyed map under one Redis key. Great for objects: user profiles, session state, anything where you want field-level updates without serialising the whole record.

HSET, HGETALL, HINCRBY, real apps

EXAMPLE
# 1) Set + read fields
HSET user:42 name Ada email ada@example.com age 32
HGET user:42 name                  # 'Ada'
HGETALL user:42                    # all fields + values
HMGET user:42 name email           # multiple by key
HKEYS user:42
HVALS user:42
HLEN user:42                        # count of fields
HEXISTS user:42 phone               # 0 or 1

# 2) Increment
HINCRBY      user:42 logins 1
HINCRBYFLOAT user:42 balance 49.99

# 3) Delete fields (vs DEL which drops the whole key)
HDEL user:42 tempToken

# 4) Atomic conditional set — like SETNX
HSETNX user:42 created_at 2026-06-08

# 5) Iterate fields without blocking (HSCAN — cursor)
HSCAN user:42 0 MATCH * COUNT 100

# 6) Node — ioredis
import Redis from 'ioredis';
const redis = new Redis();

await redis.hset('user:42', { name: 'Ada', email: 'ada@example.com', age: 32 });
const user = await redis.hgetall('user:42');
// { name: 'Ada', email: 'ada@example.com', age: '32' }

await redis.hincrby('user:42', 'logins', 1);

# 7) Real pattern — session store
await redis.hset(`session:${sid}`, {
    uid:       userId,
    csrf:      randomToken(),
    createdAt: Date.now(),
});
await redis.expire(`session:${sid}`, 60 * 60 * 24 * 14);   // 14 days

# 8) Rate limit counters — per user, per hour
const k = `rate:user:${uid}:${Math.floor(Date.now()/3600_000)}`;
const hits = await redis.hincrby(k, 'count', 1);
if (hits === 1) await redis.expire(k, 3600);
if (hits > 1000) throw new Error('rate limited');

# 9) Field-level TTL? No — TTL is per-KEY, not per-field.
# Workaround: store the field in a separate key with EXPIRE.

# 10) When NOT to use a hash
#   • Need range queries on values → use a Sorted Set
#   • Need a list / queue → use Lists / Streams
#   • Many huge fields → consider per-key STRING (one network call per read)
#   • >100k fields per hash — performance degrades; shard the key

# 11) Hash vs JSON STRING
# Hash: HSET user:42 name Ada                     - field-level updates, smaller delta
# JSON: SET  user:42 '{"name":"Ada"}'              - one read, one write, smaller key count
# RedisJSON module: JSON.SET user:42 $ '{"name":"Ada"}' — full JSON path queries

# 12) Memory-efficient — small hashes use ziplist (compact)
# Config:
#   hash-max-ziplist-entries 128
#   hash-max-ziplist-value 64

Why it matters

Use hashes for object-shaped values where you frequently update one field. Field-level HINCRBY is atomic, network-tiny, and saves a full read-modify-write cycle every time.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
HSET user:1 name "Ada" age 36
HGETALL user:1
HGET user:1 name      # "Ada"
HINCRBY user:1 age 1  # 37
Try it Yourself »

Exercise

Set a field on a hash.

user:1 name "Ada"

Discussion

Loading…