Chapter 04 · Hashes and Object-Like Records

HINCRBY/HINCRBYFLOAT for Atomic Per-Field Metrics and State

Update integer and floating-point fields atomically inside one hash while separating counter semantics from exact money, retries, cross-field invariants, and type errors.

Intermediate115–145 minutesAtomic field-counter labRedis Open Source 8.10.1Free/local-firstLast reviewed: September 6, 2026

Learning outcomes

AtlasMart records per-product views, reservation attempts, successful carts, and a rolling quality score in one metrics hash. If every worker performs HGET, computes a new number locally, then HSETs the result, concurrent updates can overwrite one another. Redis provides field-level numeric mutation commands so one command can parse, add, store, and return the result atomically for that field. The guarantee is narrower than a transaction across business fields, and the stored representation is still a Redis String.

01

Use HINCRBY for signed 64-bit integer fields and HINCRBYFLOAT for floating-point fields, including absent-field initialization.

02

Explain single-command atomicity for one field without incorrectly claiming multi-field business invariants or exactly-once retry behavior.

03

Demonstrate parsing errors, integer overflow, floating-point representation/precision, and why money should normally use integer minor units or another exact system.

04

Observe how numeric mutation interacts with field TTL, persistence, replication, and client timeouts.

05

Design counters and quotas with explicit idempotency/reconciliation rules rather than assuming Redis removes duplicate-delivery problems.

Exact lab baseline

All Chapter 04 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. This lesson mutates only small synthetic counters. It does not use floating-point fields for payments or financial ledger state.

1. HINCRBY is one atomic read-modify-write operation

HINCRBY key field increment treats a missing field as zero, adds a signed integer increment, stores the new decimal String representation, and returns the new integer. If the hash key does not exist, Redis creates it. The operation is atomic as one Redis command: another command cannot interleave a separate read and write inside that HINCRBY execution.

redis-cli · integer metric initialization and updates
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app DEL atlasmart:ch04:metric:product:1001docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:metric:product:1001 views 1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:metric:product:1001 views 4docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:metric:product:1001 reservations -1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HMGET atlasmart:ch04:metric:product:1001 views reservations# Expected: views -> 5; missing reservations starts from 0 then becomes -1.

Atomic here means the field update is not a client-side check-then-set race. It does not mean “one event is counted exactly once.” If a client times out after the server executed HINCRBY and blindly retries, the increment can be applied twice.

2. Integer range and parse failures are part of the contract

HINCRBY supports signed 64-bit integer values. A field whose bytes cannot be parsed as an integer causes an error, and an increment that would overflow the signed 64-bit range is rejected. This is different from ordinary HSET, which will store arbitrary bytes without interpreting them numerically.

redis-cli · controlled parse and overflow failures
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HSET atlasmart:ch04:metric:product:1001 bad_counter unknowndocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:metric:product:1001 bad_counter 1# Expected: ERR hash value is not an integer (wording can vary by release)docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HSET atlasmart:ch04:metric:product:1001 edge 9223372036854775807docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:metric:product:1001 edge 1# Expected: integer overflow error; edge remains unchanged.docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HMGET atlasmart:ch04:metric:product:1001 bad_counter edge

Do not repair a parse error by silently resetting a production counter to zero. First determine whether the field was corrupted, a schema rollout mixed representations, or another producer owns the same field name.

3. HINCRBYFLOAT is numeric convenience, not exact decimal accounting

HINCRBYFLOAT parses the current field and increment as floating-point values, stores a normalized decimal String result, and returns that value. As with the String command family, floating-point representation and rounding mean it is inappropriate to promise exact decimal-money arithmetic. Store currency as integer minor units such as cents when the range and currency rules permit, or use a system designed for exact decimal accounting.

redis-cli · floating metric semantics and exact-money contrast
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HSET atlasmart:ch04:metric:product:1001 quality_score 10.50docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBYFLOAT atlasmart:ch04:metric:product:1001 quality_score 0.1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBYFLOAT atlasmart:ch04:metric:product:1001 quality_score -5docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HGET atlasmart:ch04:metric:product:1001 quality_score# Fine for an approximate score/measurement.# For $24.99, prefer an exact integer field such as price_cents=2499 rather than repeated float arithmetic.

The command is O(1), but correctness is about representation and retry semantics as much as asymptotic complexity.

4. Field TTL survives numeric mutation

Hash-field expiration is cleared by operations that delete or overwrite the field contents, including ordinary HSET. Numeric increment commands conceptually alter the existing value rather than replace the field through HSET, so the field TTL remains. This distinction is useful for rolling counters but dangerous if a team assumes all writes refresh or clear expiration uniformly.

redis-cli · prove numeric mutation preserves field TTL
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HSET atlasmart:ch04:metric:product:1001 window_count 0docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HEXPIRE atlasmart:ch04:metric:product:1001 120 FIELDS 1 window_countdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HTTL atlasmart:ch04:metric:product:1001 FIELDS 1 window_countdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:metric:product:1001 window_count 1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HTTL atlasmart:ch04:metric:product:1001 FIELDS 1 window_count# Both TTL observations should remain positive, with normal elapsed-time decrease.

This does not automatically implement a rate limiter. A real rate limiter must define window creation, expiry refresh policy, retries, concurrency, clock semantics, and failover behavior. Chapter 23 handles those application patterns explicitly.

5. Atomic field update does not create a multi-field invariant

Suppose AtlasMart maintains reserved and available fields and requires reserved + available = total. Two independent HINCRBY commands can leave an observable intermediate state or partially apply if a client fails between them. A single field increment is atomic; a business invariant spanning multiple fields requires a stronger composition mechanism such as MULTI/EXEC, WATCH, a Function/script, or a redesigned primitive—covered later in the course.

redis-cli · show the boundary of single-field atomicity
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HSET atlasmart:ch04:inventory:1001 total 10 available 10 reserved 0# Two commands: each is atomic, the pair is NOT one atomic business operation.docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:inventory:1001 available -1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:inventory:1001 reserved 1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HMGET atlasmart:ch04:inventory:1001 total available reserved# Later transaction/function chapters show how to protect cross-field invariants.

6. Deliberately wrong retry: duplicate the metric

A client sends HINCRBY ... views 1, times out, and cannot tell whether the server executed it. Blind retry may produce two increments for one logical event. The repair depends on the domain: approximate telemetry may tolerate duplicates; billing or quota events may require idempotency keys, event IDs, a Stream with deduplication/reconciliation, or an authoritative downstream ledger.

redis-cli · simulate a duplicate delivery explicitly
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HSET atlasmart:ch04:metric:retry-demo processed 0# First delivery:docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:metric:retry-demo processed 1# Blind retry of the same logical event:docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:metric:retry-demo processed 1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HGET atlasmart:ch04:metric:retry-demo processed# Expected: 2 -- atomicity did not deduplicate the event.

7. Hands-on lab: bounded counters with evidence

Create one hash for product metrics, keep integer and floating fields visibly separate, add a temporary field TTL to a rolling counter, trigger a controlled parse error, and record memory/cardinality. No benchmark numbers are supplied because your host, persistence activity, payload sizes, concurrency, and Docker environment determine latency.

redis-cli · metrics evidence card
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app DEL atlasmart:ch04:lab:metricsdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HSET atlasmart:ch04:lab:metrics views 0 carts 0 quality_score 4.5 rolling_views 0 schema_version 1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HEXPIRE atlasmart:ch04:lab:metrics 90 FIELDS 1 rolling_viewsdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:lab:metrics views 7docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:lab:metrics carts 2docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBYFLOAT atlasmart:ch04:lab:metrics quality_score 0.25docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HINCRBY atlasmart:ch04:lab:metrics rolling_views 1docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HMGET atlasmart:ch04:lab:metrics views carts quality_score rolling_viewsdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HTTL atlasmart:ch04:lab:metrics FIELDS 1 rolling_viewsdocker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app HLEN atlasmart:ch04:lab:metricsdocker exec -e REDISCLI_AUTH=AtlasMart-Admin-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user academy-admin MEMORY USAGE atlasmart:ch04:lab:metrics

Verification checklist:

  • Integer fields reflect exact signed-integer results and floating fields are treated as approximate numeric measurements, not money.
  • rolling_views has a positive field TTL after HINCRBY, proving numeric mutation preserved it.
  • HLEN and MEMORY USAGE are recorded with server/version context.
  • You can explain why a timeout/retry can double an increment even though the Redis command itself is atomic.
  • No cross-field invariant is claimed to be protected by independent HINCRBY operations.
redis-cli · cleanup Lesson 2 fixtures
docker exec -e REDISCLI_AUTH=AtlasMart-App-Lab-Only-2026 atlasmart-redis-ch01 redis-cli --user atlasmart-app DEL atlasmart:ch04:lab:metrics atlasmart:ch04:metric:product:1001 atlasmart:ch04:inventory:1001 atlasmart:ch04:metric:retry-demo

8. Production judgment

Use HINCRBY for bounded counters, quotas, sequence-like numbers, and statistics where a signed 64-bit integer is the correct representation. Use HINCRBYFLOAT for measurements or scores that tolerate floating-point semantics. Do not turn either into a financial ledger, a distributed uniqueness proof, or a cross-field transaction. Monitor parse/overflow errors, hash field cardinality, hot-key traffic, latency distributions, persistence/replication pressure, and retry rates.

In Cluster, all fields of one hash live with the hash key in one slot, which simplifies single-key field updates but can make a very hot metrics hash a hot slot. Replication remains asynchronous by default; Sentinel/Cluster failover chapters will quantify acknowledged-write behavior. Search indexes over numeric hash fields add query power but also memory/write cost and should be justified by actual query requirements.

9. Summary and next step

HINCRBY and HINCRBYFLOAT perform atomic numeric mutation of individual hash fields. Missing fields start from zero; invalid representations error; integer operations are signed-64-bit bounded; floating operations are not exact decimal accounting. Numeric mutation preserves field expiration, but retries can duplicate logical events and independent increments do not create a multi-field transaction. Next, you will learn to iterate a large hash incrementally rather than fetching every field in one response.

Check your understanding

  1. What does HINCRBY make atomic?
  2. What happens when HINCRBY targets a missing field?
  3. Why should HINCRBYFLOAT not be used as an exact money ledger?
  4. Does HINCRBY clear a field TTL?
  5. Why can a timed-out increment be dangerous to retry?
Review the answers

1. The parse/add/store/result operation for the specified field in that command, not a larger business workflow.

2. Redis treats it as zero, applies the increment, and creates the field/hash as needed.

3. It uses floating-point numeric semantics and does not provide exact decimal accounting guarantees.

4. No. It mutates the field value conceptually without replacing it, so the field TTL remains.

5. The server may already have applied it; a blind retry can apply the logical event twice.

Authoritative references

  • HINCRBY — signed 64-bit per-field integer increment semantics
  • HINCRBYFLOAT — floating-point field mutation semantics
  • HEXPIRE — field expiration and TTL-clearing/preservation rules
  • Redis transactions — later composition boundary for multi-command correctness
  • Redis hashes — hash command family and field model
  • Redis replication — asynchronous replication boundary referenced in production judgment

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.