Redis Max Value Size: String Limits, Latency Spikes, and Offloading Strategies
The Redis max value size is a hard architectural limit of `512MB` for any single string key, representing the maximum byte sequence a Redis data structure can hold. While Redis permits multi-megabyte strings, values exceeding `1MB` frequently cause severe single-threaded event loop latency spikes and memory fragmentation. Production architectures avoid using Redis as a heavy object store by pairing fast in-memory key pointers with external persistent workspaces.
How Redis Enforces the 512MB String Ceiling
The Redis max value size is a hard architectural limit of 512 megabytes for any single string key, representing the maximum byte sequence a Redis data structure can hold. According to official Redis documentation, by default, a single Redis string can be a maximum of 512 MB.
While developers often think of Redis strings as simple text containers, the string type is binary-safe. A single string key can hold raw ASCII, JSON payloads, serialized language objects, raw image buffers, compressed archives, or audio fragments. Across every use case, the engine rejects any write that attempts to exceed 536,870,911 bytes (512 MB minus one byte).
Understanding why this boundary exists requires inspecting how Redis manages strings internally. Redis does not rely on standard null-terminated C strings (char*). Instead, it uses an internal abstraction called the Simple Dynamic String (SDS).
The Simple Dynamic String (SDS) Architecture
The SDS library (defined in sds.h and sds.c within the Redis source repository) prefixes raw byte arrays with metadata headers. These headers track three properties:
- Length (
len): The exact number of bytes currently stored in the string buffer. - Allocated capacity (
alloc): The total memory allocated for the buffer, excluding the header and null terminator. - Flags (
flags): A 3-bit flag identifying the header type, packed into an 8-bit unsigned integer.
To minimize memory overhead across diverse payload sizes, Redis implements five distinct SDS header structures: sdshdr5, sdshdr8, sdshdr16, sdshdr32, and sdshdr64. For small strings under 256 bytes, Redis uses sdshdr8, which dedicates an 8-bit integer to length tracking. As strings expand beyond 64 KB, Redis switches to sdshdr32, which uses 32-bit unsigned integers for both length and allocated capacity.
In the 32-bit header definition, the maximum addressable offset is bounded by 2^29 - 1 bytes (536,870,911 bytes). Redis engineers chose this architectural ceiling because it keeps string metadata compact while preserving compatibility across 32-bit and 64-bit systems. Commands that perform sub-string offsets or bit modifications enforce this limit explicitly. For example, the SETRANGE command rejects offsets exceeding 2^29 - 1, returning an engine error.
Binary Safety and the Bitmap Offset Boundary
Because Redis strings are binary-safe byte arrays, they serve as the underlying foundation for specialized Redis data structures, including Bitmaps and Bitfields.
A Redis Bitmap is not an independent data type. It is a string whose individual bits are accessed through bitwise commands such as SETBIT, GETBIT, and BITCOUNT. The maximum bit offset supported by SETBIT is 2^32 - 1 (4,294,967,295 bits). When converted to bytes, 4,294,967,295 bits divided by 8 equals 536,870,911 bytes, which aligns precisely with the 512 MB string boundary.
If an application attempts to write beyond this ceiling by issuing a SET, APPEND, or SETRANGE command that exceeds 512 MB, Redis terminates the command immediately with a protocol error:
ERR string exceeds maximum allowed size (512MB)
The write fails atomically, leaving existing keys unaltered.
Related guides
- PostgreSQL JSONB Size Limits: The `256MB` Cap, TOAST Storage, and Indexing PitfallsPostgreSQL enforces a strict `268,435,455-byte` (approximately 256 megabytes) limit on individual JSONB values,...
- Llama.cpp Context Size: How to Set -c, Calculate KV Cache, and Optimize VRAMIn llama.cpp, context size is the maximum sequence length in tokens allocated for prompt and response processing,...
- Grok Character Limit: Prompt Caps, Input Ceilings, and SolutionsThe Grok character limit depends on the access surface: when you prompt Grok through a post or reply on X, the post...
- ChromaDB Max Batch Size: Ingestion Limits and Batching PatternsChromaDB enforces a maximum batch size for vector and document ingestion to prevent SQLite variable overflow and client...
- Node.js Max Old Space Size: Increasing Heap Limits for Large DatasetsThe --max-old-space-size flag in Node.js configures the maximum memory allocation limit in megabytes for V8's old...
- DeepSeek R1 Max Output Tokens: Limits, Thinking Cutoffs, and SolutionsDeepSeek R1 max output tokens refers to the hard ceiling on completion tokens generated in a single turn, natively set...
More on this subject: AI Agents: General Guides (248 guides)
Why Large Values Trigger Latency Spikes in the Event Loop
The existence of a 512 MB ceiling does not mean storing multi-megabyte values in Redis is safe. In production environments, treating the architectural limit as an operational guideline leads to severe performance degradation. Storing string values larger than 1 MB, and especially values exceeding 5 MB, introduces multi-hundred-millisecond latency spikes that can stall entire application fleets.
The root cause lies in the execution model of Redis. Redis operates a single-threaded event loop (ae.c) to process commands. Every client connection communicates with this single thread over an event-driven multiplexer (epoll on Linux, kqueue on BSD and macOS).
The Single-Threaded Command Processing Path
Redis 6.0 introduced threaded I/O to offload socket reading and protocol parsing across multiple worker threads. However, threaded I/O does not make command execution parallel. All dictionary lookups, memory allocations, string manipulations, and data writes execute sequentially on the main thread.
When a client issues a command on a large string, the main thread must execute every phase of the operation before accepting or returning any other command:
- Memory Allocation Cost: Allocating a
20 MBor50 MBcontiguous buffer requires the memory allocator (jemalloc) to search for or carve out a matching chunk. If physical RAM is fragmented, memory allocation pauses the event loop while the OS locates contiguous virtual memory pages. - Network Serialization and Socket Buffering: Reading a
10 MBstring viaGETrequires copying10 MBfrom the Redis keyspace into the client socket output buffer. While threaded I/O handles packet transmission over the wire, assembling the response and queuing buffer blocks occurs under main thread control. - Head-of-Line Blocking: Because command execution is strictly sequential, any operation that takes
50 millisecondsblocks every other client query waiting in the socket queue. A high-throughput service handling tens of thousands of queries per second backs up thousands of pending requests during a single pause.
Memory Fragmentation and Allocator Churn
Redis relies on jemalloc as its default memory allocator on Linux. The allocator organizes memory into predefined size classes. Small strings (such as 64-byte session tokens or 256-byte identifiers) fit into tightly packed arenas with minimal waste.
When an application repeatedly creates, updates, and deletes multi-megabyte strings, memory fragmentation rises rapidly. The metric mem_fragmentation_ratio (reported via INFO memory) reflects the ratio of physical memory consumed by the Redis process (Resident Set Size, or RSS) to the memory logically allocated for keys.
When large keys are removed or overwritten, jemalloc cannot always return freed memory pages to the operating system immediately, especially if surrounding memory pages hold active small keys. As a result, RSS remains inflated at peak levels, consuming host memory and starving other processes.
The Copy-on-Write Penalty During Background Snapshots
The performance cost of large keys intensifies during persistence operations. Redis persists data to disk through two primary mechanisms: RDB snapshots (BGSAVE) and Append-Only File rewrites (BGREWRITEAOF).
Both operations rely on the POSIX fork() system call to spawn a background child process. The child process shares the parent process's memory space using the operating system's Copy-on-Write (CoW) page mechanism. When the parent process writes to a memory page after the fork, the kernel copies that 4 KB memory page before applying the modification.
If your dataset consists of millions of small keys, updates modify small numbers of pages. However, if your keyspace holds hundreds of 10 MB strings, updating a single byte within those strings triggers Copy-on-Write duplication across thousands of memory pages. During periods of frequent writes, Copy-on-Write page duplication can double Redis memory consumption in seconds, triggering kernel Out-Of-Memory (OOM) killer terminations.
Architectural Limits Versus Practical Operational Thresholds
To maintain sub-millisecond p99 latencies, engineering teams must differentiate between what Redis allows architecturally and what it handles reliably under load.
The following comparison table outlines the physical ceilings defined by the Redis engine alongside recommended operational thresholds for high-performance applications:
Client Output Buffer Disconnections
A common operational failure caused by large Redis values is abrupt client disconnection. Redis isolates each client connection with an input buffer and an output buffer. The output buffer queues response data before writing it to the network socket.
Administrators govern output buffers using the client-output-buffer-limit configuration directive:
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
When an application client queries a 30 MB string over a congested network connection, the response accumulates in the client output buffer faster than the client can consume it. If the buffer exceeds configured limits, Redis drops the socket connection immediately to protect the server from memory starvation. The application observes transient ConnectionResetError or SocketClosedException failures that are difficult to diagnose without inspecting buffer metrics.
Managing Instance Memory with maxmemory Directives
By default, Redis instances deployed without an explicit configuration do not restrict memory consumption. As documented in the official Redis memory optimization guide, if maxmemory is not set Redis will keep allocating memory as it sees fit and thus it can (gradually) eat up all your free memory. If write volume outpaces capacity, Redis consumes all available physical RAM and swap space, freezing the host system until the kernel invokes the OOM killer.
To prevent host starvation, production environments must define a strict maxmemory ceiling in redis.conf:
maxmemory 4294967296
maxmemory-policy allkeys-lru
When Redis reaches the maxmemory threshold, it enforces the configured eviction policy:
allkeys-lru: Evicts the least recently used keys across the entire dataset to make room for new writes.volatile-lru: Evicts the least recently used keys that carry an explicit expiration time (TTL).allkeys-lfu: Evicts keys with the lowest access frequency.noeviction: Refuses all incoming write commands with an OOM error while continuing to serve read queries.
If your keyspace holds multi-megabyte values, eviction policies become inefficient. Evicting a single 50 MB string frees significant memory but blocks the main thread during deallocation. Conversely, evicting thousands of small keys to accommodate one incoming 50 MB payload destroys cache hit ratios for active users.
Offload Large Payloads and Agent Corpora from Redis
Store multi-megabyte prompt libraries, agent memory traces, and reference documents in persistent Fastio workspaces. Your applications and AI agents query indexed files through MCP without bloating Redis memory or stalling the event loop. Monthly plans start with a 14-day free trial requiring a credit card.
Architectural Offloading Strategies: Pointers, Chunking, and Workspaces
When an application needs to manage multi-megabyte payloads, configuration packages, or AI agent context, forcing those payloads into Redis strings is an architectural anti-pattern. Teams resolve this tension by adopting offloading patterns that decouple metadata tracking from bulk data persistence.
Pattern 1: Payload Chunking Across Multiple Keys
For applications constrained to Redis-only infrastructure, large payloads can be split into smaller, predictable chunks across multiple keys:
HSET doc:1042:meta filename "report.pdf" total_chunks 4 byte_size 1640000
SET doc:1042:chunk:0 <binary_chunk_0>
SET doc:1042:chunk:1 <binary_chunk_1>
SET doc:1042:chunk:2 <binary_chunk_2>
SET doc:1042:chunk:3 <binary_chunk_3>
Chunking prevents individual keys from exceeding the 1 MB operational threshold, mitigating event loop latency spikes. However, chunking introduces application-side overhead:
- Reassembly Latency: The client must issue multiple
GETorMGETrequests and assemble byte slices in application memory. - Atomicity Gaps: Eviction policies or network errors can delete or fail to write individual chunks, resulting in corrupted, partial payloads.
- Keyspace Bloat: Managing millions of chunk keys complicates keyspace inspection and invalidation routines.
Pattern 2: The Claim-Check Pattern with Object Storage
The industry standard for handling large payloads is the Claim-Check pattern. Instead of storing bulk data in Redis, the application writes the raw payload to an external object store or file service. The application then stores a lightweight reference token (the claim check) in Redis:
{
"payload_id": "9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d",
"storage_uri": "s3://app-payloads/2026/10/08/payload-9b1d.bin",
"content_type": "application/json",
"byte_size": 18452100,
"sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"created_at": "2026-10-08T09:15:30Z"
}
The application saves this small JSON document (typically under 1 KB) as a Redis string or hash. Worker services read the metadata from Redis in microseconds, determine whether the payload is needed, and fetch the raw bytes directly from object storage only when required. Redis maintains high throughput, and memory consumption remains minimal.
Pattern 3: Offloading Agent Corpora to Fastio Intelligent Workspaces
For engineering teams building autonomous AI agents, LLM pipelines, and retrieval-augmented generation (RAG) systems, the payload problem is pronounced. Modern agents generate and consume extensive context: detailed tool execution logs, conversation histories, codebase repositories, technical manuals, and multi-megabyte document bundles.
Attempting to store these corpora inside Redis strings rapidly exhausts memory and causes event loop stalls. Storing them in raw object buckets solves the byte capacity issue but leaves the files inert, requiring developers to construct and maintain custom vector databases, chunking scripts, and synchronization jobs.
A more complete solution is offloading agent context to an intelligent workspace platform like Fastio:
- Automatic Hybrid Indexing via Workspace Intelligence: Files placed in a Fastio shared workspace are automatically indexed for hybrid search, combining full-text keyword retrieval with semantic vector search. An AI agent querying a
50 MBtechnical manual or prompt library does not load the entire file into Redis or its prompt window. Instead, the agent performs a search query and retrieves only the exact passages needed. - Structured Extraction with Metadata Views: When teams require structured querying across document sets, Fastio's Metadata Views convert documents into queryable tables. Users define fields in plain language, and the extraction engine generates typed schemas (Text, Integer, Decimal, Boolean, URL, JSON, Date & Time) across PDFs, Word documents, spreadsheets, and scanned files without manual OCR templates.
- Direct MCP Integration for Autonomous Agents: Fastio exposes remote Model Context Protocol (MCP) server endpoints over Streamable HTTP. Coding agents connect via
https://mcp.fast.io/mcp/code, while Claude and general agents connect viahttps://mcp.fast.io/mcp/tools(refer to the MCP setup documentation for configuration steps). Agents read, write, and search persistent storage for AI agents directly through standardized tool calls. - Concurrency Coordination and Version History: When multiple agents collaborate within shared workspaces, Fastio preserves complete per-file version history and maintains a detailed activity log. Advisory file locks (
lock-acquireandlock-releaseactions on thestorage_managetool) coordinate access across distributed agents without granting exclusive overwrite rights.
Monthly plans start with a 14-day free trial, which requires a credit card. Subscription tiers scale across Starter ($9.99/mo for 3 seats, 250 GB storage, 5 workspaces, and 100,000 credits), Business ($49.99/mo for 10 seats, 5 TB storage, 50 workspaces, and 600,000 credits), and Enterprise ($199.99/mo for 30 seats included, 25 TB storage, 200 workspaces, and 3,000,000 credits) on the pricing page. Credits meter AI operations; overage is $10 per 100,000 credits. Additional storage is billed at 1.5 cents per GB a month and extra bandwidth at 4 cents per GB.
Auditing, Detecting, and Mitigating Large Keys in Production
If your application already runs against Redis in production, identifying and eliminating oversized keys prevents latency spikes and avoids unexpected out-of-memory crashes.
1. Scan for Large Keys Non-Blockingly with redis-cli
Never execute the KEYS * command on a production Redis instance. KEYS runs synchronously in $O(N)$ time and blocks the event loop until every key in the keyspace is scanned.
Instead, use the built-in --bigkeys scanner provided by redis-cli:
redis-cli -h 127.0.0.1 -p 6379 --bigkeys
The --bigkeys command uses the non-blocking SCAN command to traverse the keyspace incrementally without stalling active client traffic. As it samples the keyspace, it reports the largest key encountered for each data type:
-------- summary -------
Sampled 145020 keys in the keyspace!
Total key length in bytes is 4205574 (avg len 29.00)
Biggest string found 'session:blob:9481' has 14680064 bytes
Biggest hash found 'customer:profiles' has 420 fields
Biggest list found 'jobs:incoming' has 1240 items
Biggest set found 'tags:active' has 85 members
Biggest zset found 'leaderboard:global' has 5120 members
In the example output above, the scanner immediately identifies session:blob:9481 as a 14 MB string, providing a clear target for architectural remediation.
For deeper memory profiling, the --memkeys argument samples keys and ranks them by actual memory consumption rather than raw element counts:
redis-cli -h 127.0.0.1 -p 6379 --memkeys
2. Inspect Specific Key Footprints with MEMORY USAGE
To measure the exact memory consumed by a suspected key, use the MEMORY USAGE command:
127.0.0.1:6379> MEMORY USAGE session:blob:9481 SAMPLES 5
(integer) 15204352
MEMORY USAGE returns the total number of bytes allocated for the key, including the SDS string buffer, the dict entry metadata, and internal allocator padding. The optional SAMPLES argument controls how many nested elements Redis samples when evaluating aggregate data structures.
3. Diagnose Event Loop Latency with SLOWLOG and Latency Monitoring
When large values stall the server, Redis logs the offending operations in its slow query log. Query the slow log using SLOWLOG GET:
127.0.0.1:6379> SLOWLOG GET 5
1) 1) (integer) 34
2) (integer) 1728378930
3) (integer) 48200
4) 1) "GET"
2) "session:blob:9481"
5) "10.0.1.42:54210"
6) ""
The execution time is recorded in microseconds. In this entry, retrieving session:blob:9481 blocked the event loop for 48,200 microseconds (48.2 milliseconds).
To capture intermittent latency events automatically, configure Redis latency monitoring:
127.0.0.1:6379> CONFIG SET latency-monitor-threshold 20
127.0.0.1:6379> LATENCY DOCTOR
Setting latency-monitor-threshold 20 instructs Redis to log any internal event that exceeds 20 milliseconds. The LATENCY DOCTOR command analyzes recorded events and produces automated operational diagnostics.
4. Delete Large Keys Safely with UNLINK
When an application deletes a large key using the traditional DEL command, Redis immediately frees the associated memory pages on the main thread. Deleting a 50 MB string or a hash with hundreds of thousands of fields can block the event loop for 100 milliseconds or longer.
To eliminate deletion latency, use the UNLINK command instead:
127.0.0.1:6379> UNLINK session:blob:9481
(integer) 1
UNLINK performs an $O(1)$ operation on the main thread by removing the key reference from the database keyspace. The actual memory deallocation is offloaded to a background I/O thread, allowing Redis to continue serving client requests without interruption.
To enable asynchronous memory reclamation globally across expiration and eviction events, update your redis.conf with lazy-free directives:
lazyfree-lazy-eviction yes
lazyfree-lazy-expire yes
lazyfree-lazy-server-del yes
replica-lazy-flush yes
These settings guarantee that when Redis evicts keys or processes expirations under memory pressure, memory deallocation occurs asynchronously on background worker threads.
Sources
References used to verify factual claims in this guide.
-
By default, a single Redis string can be a maximum of 512 MB.
-
If maxmemory is not set Redis will keep allocating memory as it sees fit and thus it can (gradually) eat up all your free memory.
Frequently Asked Questions
What is the maximum size of a value in Redis?
The maximum size of a single value in Redis is 512 megabytes (`536,870,911 bytes`). This limit applies to all string values, binary payloads, and data structures implemented on top of the Simple Dynamic String (SDS) architecture, including Bitmaps and Bitfields.
Can Redis store files larger than `512MB`?
Redis cannot store any single key value exceeding `512 megabytes`. To store larger files, applications must either split the payload into multiple discrete chunk keys across the keyspace or adopt the Claim-Check pattern by persisting the file in external workspace storage while maintaining a lightweight pointer in Redis.
Why does storing large objects in Redis cause high latency?
Redis executes commands sequentially on a single-threaded event loop. When a client reads, writes, or deletes a multi-megabyte object, the main thread is occupied with memory allocation, buffer serialization, and network copying, blocking all subsequent client queries and causing p99 latency spikes.
What error occurs when writing a string larger than `512MB` to Redis?
When a command attempts to write or append data exceeding `512 megabytes` to a Redis string key, the engine rejects the operation immediately and returns the protocol error: 'ERR string exceeds maximum allowed size (512MB)'.
How does the UNLINK command differ from DEL for large Redis keys?
The DEL command removes a key and frees its allocated memory synchronously on the main thread, causing event loop stalls when handling large keys. The UNLINK command unbinds the key from the keyspace in O(1) time and offloads memory deallocation to a background worker thread.
What is the recommended maximum value size for Redis in production?
Production best practices recommend keeping individual Redis string values below `100 KB`, with an optimal target below `10 KB` for high-throughput caching. Values exceeding `1 MB` introduce significant event loop latency, memory fragmentation, and socket buffer risks.
How does client-output-buffer-limit affect clients reading large Redis values?
When a client requests a large string over a congested network connection, response data accumulates in the server output buffer. If the buffer breaches the configured client-output-buffer-limit threshold, Redis immediately closes the client socket to prevent memory exhaustion.
Related Resources
Offload Large Payloads and Agent Corpora from Redis
Store multi-megabyte prompt libraries, agent memory traces, and reference documents in persistent Fastio workspaces. Your applications and AI agents query indexed files through MCP without bloating Redis memory or stalling the event loop. Monthly plans start with a 14-day free trial requiring a credit card.