Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
From Redis 7 to Redis 8.x and Valkey 9: What's New, Where They Diverge and Migrating StackExchange.Redis 2→3
Neither Redis 7.4 nor Valkey 9 can open an RDB file written by Redis 8; Redis and Valkey share 7.2 as their common ground, and upgrades are one-way. With real measurements: RDB and replication compatibility, a summary of Redis 8.0–8.10, a compatibility table built by asking both servers with COMMAND DOCS, old APIs that are compile errors in StackExchange.Redis 3.x, and a version upgrade plan.
Running Redis in Production: ACL, TLS, Dangerous Commands, Latency Diagnosis, OpenTelemetry and Testcontainers
In production every application should connect to Redis with its own ACL user that may use only the commands, keys and channels it needs; a user without FLUSHALL, KEYS and EVAL is the first defence against Lua vulnerabilities and a leaked password. With real output: what ACL LOG reveals, moving to Functions, TLS, reading SLOWLOG and the StackExchange.Redis timeout message, OpenTelemetry spans and integration testing with Testcontainers.
Replication, Sentinel and Cluster in Redis: Failover, Hash Slots, Hash Tags and CROSSSLOT
Because Redis replication is asynchronous, a write acknowledged to the client can be lost in a failover; WAIT does not prevent this, it only makes it visible. With real output: a lost order number, failover time with Sentinel and StackExchange.Redis, 16384 hash slots in Cluster, MOVED, CROSSSLOT and hash tags, Functions that must be loaded on every primary, node-local keyspace notifications, Redis 8.4's atomic slot migration and how Valkey 9 differs.
Redis Persistence and Memory Management: RDB, AOF, fsync, Fork Cost, maxmemory and Big/Hot Keys
The official redis:8 image takes only periodic RDB snapshots by default; if the container dies with SIGKILL everything after the last snapshot is gone, while with AOF everysec no order was lost in the measurement. With real output: fork and copy-on-write cost, turning on AOF without losing data, Redis 8.10's BACKUP command, noeviction protecting a stream, OOMKilled, UNLINK, HOTKEYS and the activedefrag threshold.
Redis JSON and the Query Engine: JSON Documents, FT.CREATE, FT.SEARCH, FT.AGGREGATE and NRedisStack
In Redis 8 you can partially update JSON documents with JSONPath and filter and sort them with FT.SEARCH over an index built with FT.CREATE; search sees the new value as soon as the write command returns. With real output: catalog search with NRedisStack, tag escaping, GROUPBY counting only the first value of multi-value fields, the limits of Turkish stemming and the dotted capital I, index cost for 100,000 books and how valkey-search differs.
Redis Streams: Consumer Groups, the Pending Entry List, XAUTOCLAIM and Idempotent XADD
In Redis Streams a consumer group keeps every event it handed out but that was not acknowledged in the pending entry list; a crashed worker's work is not lost and moves to another worker in a single read with Redis 8.4's XREADGROUP CLAIM. With real output: stream structure, two independent consumer groups, immediate retry with XNACK, Redis 8.6's idempotent XADD with IDMP, a BackgroundService worker, a dead-letter stream for poison messages and XTRIM's default 10,000-entry limit.
Redis Pub/Sub and Keyspace Notifications: Sharded Pub/Sub, At-Most-Once and Cache Invalidation Signals
Redis pub/sub delivers a message only to the listeners connected at that moment and stores it nowhere; a message published while a connection is down never arrives. With real output: at-most-once delivery, message order with a handler versus a ChannelMessageQueue, a 40 MB GET dropping a shared connection, L1 invalidation across two API instances, a work-available signal for a queue, sharded pub/sub, late expired events, hash field notifications and a slow subscriber.
Atomicity in Redis: MULTI/EXEC, WATCH, Lua Scripts and Redis Functions
In Redis, MULTI/EXEC runs commands in order with nobody in between, but it does not roll back; for multi-step work that decides based on a read, the right tool is usually a Lua script. With real output: a stock of 100 copies sold 200 times, 14,620 retries with WATCH, StackExchange.Redis conditions, stock reservation with LuaScript.Prepare, the script cache, Redis Functions surviving a restart, Redis 8.8's INCREX and a long script that locks the server.
Special Data Types: Bitmaps, HyperLogLog, Geospatial and Probabilistic Structures (Bloom, Cuckoo, Top-K)
For unique counting, a bitmap gives the exact result with about a fiftieth of a set's memory when identities are dense; HyperLogLog counts any kind of identity in 12 KB with roughly 1 % error. With real output: set, bitmap and HLL on the same visitor data, the 14 MB trap of a sparse bitmap, BITFIELD, Geo for the nearest warehouse, a Bloom filter's measured memory and false positive rate, Cuckoo, Top-K, Count-Min Sketch, t-digest, Redis 8.8's Array and the Valkey differences.
Redis Sorted Sets: Leaderboards, Time-Windowed Rankings and Pagination
A Redis sorted set keeps every member with a score and stays ordered at all times; rank and page queries on a leaderboard take microseconds even with a million members, but paging a live list by rank drifts between two requests. With real output: ZADD options, paging with ZRANGE, the week's bestsellers from daily sets with ZUNIONSTORE and Redis 8.8's COUNT, the order of equal scores, the 2^53 precision limit, and sliding windows that use a timestamp as the score.
Redis Hashes: Storing Objects, Field Expiration and Memory Efficiency
A small Redis hash lives in the listpack encoding and holds the same cart in half the memory of a JSON string and well under half of separate keys; the 513th field or a single 65-byte value turns it into a hashtable and multiplies memory by 3.4. With real output: Bookstore's cart with HashEntry, choosing between a hash and JSON, a per-field price lock with HEXPIRE and HSETEX, Valkey's encoding difference, Redis 8.10's compact hashes via HIMPORT, and a 44 ms HGETALL on a huge hash.
Redis Strings and Expiration: SET Options, Counters, Compare-and-Set and TTL Semantics
Overwriting a Redis key with SET removes its TTL; rewrite a verification code without EX and it is never deleted. With real output: SET options and KEEPTTL, a daily counter with INCR and EXPIRE NX, GET + SET losing 9,617 of 10,000 increments, a one-time code and an idempotency key built on Redis 8.4's SET IFEQ, DELEX and DIGEST, the Valkey differences, and how expiration works inside through lazy and active deletion.