Summary
- RFC 10022 makes a requested batch size a hard maximum, not an exact count. A returned UID interval may contain fewer messages, and its boundary UIDs need not identify messages that exist.
OK UIDBATCHES completedcloses the calculation, not the later job. A defensible result preserves the selected mailbox and UIDVALIDITY, the plan response, concurrent change evidence, every execution receipt and an explicit disposition for vanished, new and unresolved messages.
Four ranges, one dangerous sentence
Take the example built into RFC 10022. A selected mailbox contains 6,823 messages. The client requests batches of 2,000. The server returns four descending UID ranges and ends the command with OK UIDBATCHES Completed.
Now imagine the result entering an operations console. The console turns four ranges into four work items. A scheduler marks the planning stage green. An executive summary shortens that to “mailbox divided successfully.” Hours later, someone writes the sentence that causes the real problem: “All 6,823 messages were processed.”
Nothing in the batch response proves that sentence.
The command computed boundaries for later work. It did not fetch a body, update a flag, copy a message, move a message, export a record or verify that an application accepted one. Even the population represented by a range is deliberately approximate within limits. A range endpoint may be an unoccupied point in UID space. Deletions can remove members after the plan is returned. New messages take higher UIDs and sit above the previous plan. The server can correctly return fewer messages than the requested size.
This is not a defect hidden in the specification. It is the design. RFC 10022 gives a client a portable way to predetermine coarse UID ranges, particularly when UIDONLY has removed access to message sequence numbers. It preserves a useful optimisation without pretending that a live mailbox became a static array.
The operating mistake is to let a successful planning verb borrow the authority of the execution verbs that follow it.
The number is a ceiling, not a promise
The request argument looks like a cardinality: UIDBATCHES 2000. A hurried reader may expect every range except the last to contain exactly 2,000 existing messages. RFC 10022 makes a different contract.
The server must never return a range containing more messages than the client requested. That is the hard boundary. On the other side, the server should return ranges close to the requested size and should aim for at least 90% when possible. But it may return fewer when that makes the implementation materially simpler or more efficient, and when mailbox state changes during the calculation, especially through expunges.
The asymmetry is operationally important. “No more than 2,000” is enforceable. “Exactly 2,000” is not. A client can safely use the range as an upper-bound work unit. It cannot infer an exact inventory from the width of the interval or the requested number.
There is also a floor. A client must request at least 500 messages per batch; a smaller request receives NO [TOOFEW]. The floor does more than protect performance. UIDONLY intentionally denies fine-grained sequence positions. Allowing batch size one would recreate those positions through another door. Coarse batching therefore protects the architecture as well as the server.
This division of authority is clean. The client chooses a useful upper bound. The server chooses valid interval boundaries under its storage and efficiency constraints. Neither party acquires the right to call the interval an exact census.
A UID at the edge may name nothing
UIDs persist within a mailbox generation, but UID space can contain holes. Messages are deleted. Implementations can select convenient interval endpoints. RFC 10022 consequently allows a server to return ranges whose first or last UID does not correspond to any message currently stored.
That rule feels surprising only if the interval is mistaken for a list. It is closer to a fence around a work area. A boundary can stand between occupied positions. When the client later issues UID FETCH 163886:99703, the server applies ordinary IMAP semantics to the messages that actually exist inside that range. It does not materialise the nonexistent endpoints.
The last range illustrates the point elegantly. A server may end it at UID 1 even if the lowest existing message has UID 302. UID 1 makes it unambiguous that the interval is the oldest and final batch. It does not assert the existence of message 1.
This distinction should survive every data model built around the extension. Store the returned interval as a boundary pair, not as two verified message objects. Do not create a synthetic receipt for an endpoint. Do not estimate completion from numeric width. If exact membership matters, record the messages actually returned by the later command.
The prior IMAP identity rule still applies. A durable message reference is scoped by mailbox identity, UIDVALIDITY and UID. A UIDBATCHES result adds a plan epoch; it does not replace the mailbox generation or authenticate the content found at a UID.
A plan can shrink and still remain valid
Within one mailbox generation, new messages receive higher UIDs. They cannot appear inside an already returned interval. That gives the plan a valuable monotonic property: its old bands will not acquire newly delivered messages in the middle.
They can lose members. Expunge removes a message and leaves a hole. If an interval initially covered 2,000 messages and ten are deleted, the interval now leads later commands to at most 1,990 of those old members. The plan may still be useful; its cardinality has changed.
New arrivals create the opposite condition. They sit above the former high-water mark and belong to a new working batch. They do not invalidate the geometry of the old intervals, but they can invalidate an operational statement such as “the entire mailbox is covered.” That statement needs a cutoff.
RFC 10022 deliberately limits recalculation because computing batches can be expensive. A client must not resend the command whenever it wants cosmetic freshness. Recalculation becomes appropriate when a different mailbox is selected, when more than half a batch has been expunged, or when more than half a batch of new messages has arrived. A server should track requests and mailbox changes and may reject abusive recomputation with LIMIT.
The result is a two-clock system. Protocol validity answers whether the old ranges remain usable. Business completeness answers whether the job's intended population has moved enough that a new epoch is required. The thresholds help bound server work; they do not decide an organisation's export, retention, legal-hold or migration obligation.
If the job is “process every message present at 09:00,” later arrivals may be assigned to the next epoch while expunged messages need an explicit unavailable outcome. If the job is continuous synchronisation, the new high-UID batch may enter immediately. Same protocol, different local decision. The common layer should not pretend to own the policy.
Empty and OK are compatible
RFC 10022 requires an untagged UIDBATCHES response even when it contains no ranges. The response carries the tag of the command it answers, following the correlator pattern used by ESEARCH. A tagged OK then closes the command.
An empty range list can arise because the mailbox is empty. It can also arise because the client requested batch indices that do not exist. Suppose a 7,000-message mailbox produces only four batches of 2,000, and the client asks for batches 6 through 8. The correct answer is an empty UIDBATCHES response followed by OK.
The bytes alone therefore do not carry the whole meaning. The selected mailbox, UIDVALIDITY, request tag, batch size, requested index window and contemporaneous mailbox state are part of the evidence. “Empty plus OK” proves that the server processed a valid request and had no ranges for that request. It does not, without context, prove that the mailbox contains no messages.
Error states also stay distinct. TOOFEW says the requested batch size fell below the supported minimum. TOOMANY says the requested or all-ranges response exceeded a bounded capability. LIMIT can identify prohibited recalculation pressure. BAD [CLIENTBUG] can reject a batch-index window written in descending rather than ascending order. Collapsing them into “batching failed” destroys the decision information the protocol provides.
Large mailboxes make authority visible
A batch-index request must not span more than 100,000 messages. A server must at least support returning ranges across that population. For an extremely large mailbox, an unwindowed request for every batch may still produce NO [TOOMANY].
That is not a strange edge case. It is the moment the extension reveals who owns which cost. The client wants a global plan. The server owns the computation and response surface. The protocol establishes a minimum interoperable capacity, then permits the server to refuse an unbounded calculation.
The optional batch-index window is how the client localises the work. If it asks for consecutive windows across a mailbox that may change between calls, RFC 10022 suggests overlapping the windows—for example, requesting 1:100, then 100:200. Comparing the overlap can reveal inconsistency. It cannot freeze the mailbox, choose the right answer automatically or recover an already vanished message.
Overlap is witness evidence. It is useful because it makes drift visible. Treating the duplicate window as wasted work misses its function; treating it as perfect consistency proof gives it too much power.
This is Running-Code Primacy in a modest but practical form. A published command defines the common transaction. The actual server still has to compute, limit and answer it. The operator still has to compare the overlap and decide whether observed drift matters. A registry entry cannot perform any of those acts.
Neighbouring extensions do not merge into one capability
RFC 10022 was designed to coexist with several IMAP extensions. Their borders are part of the article's thesis.
UIDONLY removes message sequence numbers from an enabled connection. Commands must use UID forms, and expunge information is expressed through VANISHED. UIDBATCHES offers coarse UID intervals without restoring the fine positional view that UIDONLY removed. The 500-message floor helps preserve that boundary.
PARTIAL pages actual SEARCH results or limits a UID FETCH response. UIDBATCHES instead prepares ranges that a client can reuse across different later commands. A PARTIAL response reports a subset of a query result; a UIDBATCHES response reports a work partition. One does not certify the other.
SEARCHRES lets a SEARCH result be saved in $. RFC 10022 explicitly says UIDBATCHES is not SEARCH or UID SEARCH and must not populate $. A batch plan is not silently promoted into a saved message set.
QRESYNC and CONDSTORE can help a client learn about changes, modification sequences and vanished messages. They strengthen the evidence around drift. They do not retroactively turn an old plan into a new snapshot.
MESSAGELIMIT allows a server to advertise how many messages a later SEARCH, FETCH, STORE, COPY, MOVE, APPEND or UID EXPUNGE can process under its contract. When both extensions are present, the client should choose a UIDBATCHES size no greater than the advertised downstream limit. A batch plan that contains at most 2,000 messages is still unusable for one FETCH if the server's execution limit is 1,000.
Capability composition is therefore an intersection, not a pile of green badges. The usable batch is bounded by UIDBATCHES, the actual later verb, mailbox state and any advertised execution limit.
Closeout needs populations, not a progress bar
A progress bar usually divides “completed batches” by “planned batches.” That ratio can look precise while answering the wrong question. Four of four intervals attempted does not show whether every intended message reached a terminal outcome.
A stronger model keeps seven populations:
| Set | Evidence question |
|---|---|
P |
Which messages belong to the job policy and mailbox generation? |
B |
Which existing messages were discoverable through the returned intervals at plan time? |
A |
Which messages were actually addressed by later commands? |
C |
Which messages received a terminal accepted result? |
X |
Which intended messages were observed expunged or vanished? |
N |
Which new messages arrived above the plan's high-water mark? |
U |
Which outcomes remain unknown or retryable? |
For a bounded export, a defensible rule might require P = C ∪ X, an empty U, and a reason for every member of X, while assigning N to the next epoch. For a migration that must include arrivals until cutover, N may be added to a new batch and the cutoff advanced. For a read-only indexer, expunge may be an expected terminal state rather than an exception.
Counts cannot prove the equation. If one intended message vanished and one unrelated new message completed, the totals may balance while membership is wrong. Reconciliation needs the mailbox name, UIDVALIDITY, UID, job epoch and command result.
This is the real value of RFC 10022. It gives a scalable way to divide work without demanding that all later systems share one implementation. It does not create a central authority over completion. Each participant can verify its own bounded facts, and leadership can define the local equation that converts those facts into a decision.
What the public record does not prove
RFC 10022 records an interoperable capability and its limits. It does not establish that a named provider deploys it, that a particular client respects recalculation rules, that one implementation reaches the 90% recommendation, or that a production mailbox has ever returned a nonexistent endpoint UID.
The scenarios here are operating tests, not reported incidents. The standard proves that the states are permitted or required by the protocol. It does not supply prevalence, customer harm or vendor attribution.
The IANA registry proves that UIDBATCHES, TOOFEW and TOOMANY have assigned meanings. It does not show that a running server advertises them or implements them correctly. RFC status fixes the shared vocabulary; adoption remains voluntary and execution remains local.
That boundary matches Heng Lu's insistence that a documentary layer should never be inflated into operational fact. Reality is preserved by keeping declaration, stored state and observed effect separate. Here the declaration is CAPABILITY, the stored planning state is the range response, and the effect is the later command result for actual messages.
Sources
- RFC 10022 — IMAP UIDBATCHES Extension
- RFC Editor publication record for RFC 10022
- RFC 9051 — Internet Message Access Protocol, Version 4rev2
- RFC 3501 — Internet Message Access Protocol, Version 4rev1
- RFC 9586 — IMAP UIDONLY Extension
- RFC 9394 — IMAP PARTIAL Extension for Paged SEARCH and FETCH
- RFC 4731 — IMAP4 Extension to SEARCH Command for Controlling What Kind of Information Is Returned
- RFC 7162 — IMAP Extensions: Quick Flag Changes Resynchronization and Quick Mailbox Resynchronization
- RFC 5182 — IMAP Extension for Referencing the Last SEARCH Result
- RFC 9738 — IMAP MESSAGELIMIT Extension
- IANA — Internet Message Access Protocol Capabilities Registry
- Heng Lu — Running-Code Primacy
- Heng Lu — Minimum Initial Specification, Localized Future Decision, and Voluntary Adoption
- Heng Lu — On Reality Layers
- Heng Lu — On Data Sovereignty
Member Briefing
Deeper Profile Context
Sign in with the right membership level to unlock the full briefing and source notes.
Only for Strategic Circle
Strategic Circle
Open to all readers. Unlock profile briefings after joining and signing in.
Join Strategic CircleOnly for Leadership Alliance
Leadership Alliance
For qualified IP-asset owners and management; sign in to unlock alliance briefings.
Join Leadership Alliance
