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 # 37Try it Yourself »
Exercise
Set a field on a hash.
user:1 name "Ada"
Four letters.
Discussion
Loading…