In redis.conf, 1g and 1gb are different numbers

30 July 2026

There is a tool for this on the site

Redis accepts both of these and they do not mean the same thing:

maxmemory 1g
maxmemory 1gb

1g is one billion bytes. 1gb is 2³⁰, which is 1,073,741,824. The difference is about 7%, and the version without the b is the smaller one.

The rule

From the comment in Redis’s own default configuration file:

# 1k  => 1000 bytes
# 1kb => 1024 bytes
# 1m  => 1000000 bytes
# 1mb => 1024*1024 bytes
# 1g  => 1000000000 bytes
# 1gb => 1024*1024*1024 bytes

A bare suffix is decimal. A suffix with b is binary.

This is the opposite of the convention almost everywhere else, where GB is the ambiguous decimal one and GiB is the explicit binary one. Redis uses neither notation, and its shorter form is the decimal one, which is the direction nobody guesses.

The units are case-insensitive, so 1GB and 1gb are identical. It is the presence of the b that decides, not the capitalisation, which means a config written in a house style of uppercase units is unaffected and one written tersely is not.

Why the smaller number is the dangerous direction

If you meant 1 GiB and wrote 1g, Redis is now capped 73 megabytes below what the capacity plan assumed. On a 1 GB instance that is 7% of the budget gone before any data is written.

Nothing fails at startup. Nothing appears in the logs. CONFIG GET maxmemory returns bytes, so it will tell you the truth if you ask, and nobody asks.

The instance runs normally until it reaches the cap, at which point the eviction policy engages earlier than modelled. The symptom is a hit rate a few points below projection with no obvious cause, or on noeviction, write errors at a memory figure that does not match the configured one.

Seven percent is small enough to be attributed to almost anything: a traffic change, a new feature, a bigger average value. It is rarely attributed to the config.

It is not just maxmemory

Every size in redis.conf goes through the same parser:

SettingWhat a 7% error does
maxmemoryEviction starts early, or writes fail early
client-output-buffer-limitReplicas and pub/sub subscribers disconnect under load sooner than sized
repl-backlog-sizeA shorter disconnect window before a partial resync becomes a full one
proto-max-bulk-lenA slightly smaller maximum value size

client-output-buffer-limit is the one to look at twice, because it takes two sizes on one line, a hard limit and a soft limit:

client-output-buffer-limit replica 256mb 64mb 60

Getting either 7% smaller than intended means replica disconnections under load you have already sized against, and a replica that disconnects triggers a resync, which increases load, which makes the next disconnect more likely. It is the one place where this small error has a feedback loop attached.

repl-backlog-size matters for the same reason: too small and a brief network blip turns a cheap partial resynchronisation into a full RDB transfer.

The wrong instinct: convert everything to bytes

The obvious fix is to write raw byte counts and remove the ambiguity. It works and it is worse to read: 1073741824 in a config file tells the next person nothing and invites a typo that is invisible.

Write the b. maxmemory 1gb is unambiguous, is almost always what was meant, and reads correctly. If you genuinely want decimal, that is the case for writing it out in bytes with a comment saying why, because a bare 1g will be “corrected” to 1gb by the next person who reads this article.

The bigger error next door: overhead is not payload

Worth raising alongside, because a team that has just fixed a 7% unit error is usually still carrying a much larger sizing error.

maxmemory bounds what Redis reports as used_memory, and that is not the size of your values.

Per-key overhead. Every key carries a robj header, a dictionary entry, and the key string itself. For small values this dominates: ten million keys holding 100-byte strings is nowhere near 1 GB.

Allocator rounding. jemalloc rounds each allocation up to a size class, so a 33-byte string does not occupy 33 bytes. The rounding is bounded but not small in aggregate.

Encoding cliffs. Small collections are stored in a compact listpack encoding until they cross a threshold (hash-max-listpack-entries, hash-max-listpack-value and their list, set and zset equivalents), at which point the representation switches to a hashtable or skiplist and memory per element jumps discontinuously. One extra field on a hash can move it across that line and multiply its footprint.

That last one is why linear capacity projections fail. “We have ten million keys averaging 100 bytes, so we need a gigabyte” is wrong by a factor that depends on your key lengths and your encoding thresholds, and the error is not a constant you can multiply in.

Two things to check on a live instance:

> INFO memory
used_memory:2147483648
used_memory_rss:2952790016
maxmemory_policy:allkeys-lru
mem_fragmentation_ratio:1.37
> MEMORY USAGE mykey
(integer) 168

MEMORY USAGE on a representative sample of real keys, multiplied out, beats any estimate from value sizes. It is the closest thing to a measurement available without a full dump.

What changed recently

listpack replaced ziplist as the compact encoding for hashes, lists and zsets in Redis 7.0, and the config names changed with it: hash-max-ziplist-entries became hash-max-listpack-entries. The old names are still accepted as aliases, so a config carried forward works and does not signal that the newer tuning knobs exist.

Sets got a listpack encoding too in 7.2, via set-max-listpack-entries. Small sets of non-integer values used to jump straight to a hashtable and now do not, which changes the memory profile of anything using many small sets.

Redis 8 folded several modules into the core, which shifts the baseline used_memory on a fresh instance. Not large, and worth re-baselining rather than reusing a number from an older version.

Sizing an instance properly

1. Fix the units first. Grep the config for a size without a b and decide whether it was intended.

2. Measure, do not estimate. Load a realistic sample, read used_memory, divide by the key count. Ten thousand real keys tells you more than any calculation.

3. Check where your collections sit relative to the encoding thresholds. If a typical hash has 120 fields and the threshold is 128, you are one product change away from a step increase across the whole keyspace.

4. Leave headroom for fragmentation. mem_fragmentation_ratio above about 1.5 means the process is holding substantially more RSS than Redis is using. Below 1.0 means the opposite and is worse: the instance is swapping, which for a single-threaded in-memory store is close to an outage.

5. Set maxmemory below the container limit, not equal to it. Redis enforces its own cap against used_memory, and the kernel enforces the container limit against RSS. If those are the same number, fragmentation alone gets you OOM-killed while Redis believes it has room.

When the units do not matter

If you set maxmemory in bytes or with an explicit b, this is already a non-issue and the rest of the sizing advice is the useful part.

If you are not running with a maxmemory at all, which is the default, the unit question is moot and you have a different problem: an instance with no cap will grow until the kernel intervenes, and the OOM killer is a worse eviction policy than any of Redis’s.

On a dedicated host with generous headroom, 7% may be genuinely irrelevant. The reason to fix it anyway is that the next person to read the config will assume binary, and the gap between what is written and what is meant is the part that eventually costs something.

The short version

  • Bare suffix is decimal, suffix with b is binary. 1g < 1gb, by 7%.
  • Case does not matter. The b does.
  • It applies to every size in redis.conf, including the two-value client-output-buffer-limit.
  • No error, no log line. CONFIG GET returns bytes and will tell you.
  • The bigger sizing error is usually overhead: per-key structures, jemalloc rounding, and encoding cliffs that are step functions rather than slopes.
  • Measure with MEMORY USAGE on real keys. Do not project from value sizes.
  • Set maxmemory below the container limit, because they measure different things.

The Redis memory calculator models per-key overhead, jemalloc size classes and the encoding thresholds, and reports the element count at which a collection changes representation, which is the cliff that turns a linear projection into a wrong one.