Internet Protocols · Protocol Design
Registry Allocation Policy and the Cost of a Code Point
How IANA registries decide who gets a number, why allocation policy is a protocol design decision, and how scarce identifier spaces shape what can be built.
Every extensible protocol needs a namespace. The namespace is usually a range of integers, and the question of who may take a value from it is not an administrative detail. It determines how quickly the protocol can evolve, how much interoperability the values guarantee, and whether an implementer with a good idea can test it without asking permission.
The IETF’s answer is a set of allocation policies, each a different trade between openness and assurance. Understanding them requires understanding what a registry entry actually promises, because the promise differs by policy and implementers routinely assume more than the policy provides.
What a registry entry does and does not guarantee
A registration records that a value is assigned to a purpose, and names a document that defines the purpose. That is the whole of it. The registry does not certify that the defining document is correct, that implementations exist, that they interoperate, or that the value will never be reassigned. It is a coordination record.
The value of the record is that it prevents two independent designs from colliding. Without it, two implementations could pick the same extension type for different purposes, and a receiver would have no way to distinguish them. With it, the type identifies one purpose, and the receiver’s behaviour is determined.
The cost of the record is latency. A new value requires a document, and a document requires review, and review requires people. The latency is measured in months for the lighter policies and years for the heavier ones. During that latency, the protocol cannot deploy the feature, so implementations either wait or ship something unregistered.
Unregistered values are not necessarily a violation, but they are a problem: they consume a value from a range that might later be allocated, and the collision produces exactly the ambiguity the registry exists to prevent. This is why private-use ranges exist, and why a protocol that allocates its entire space to public use has no room for experiments.
The policy ladder
The policies form a ladder from most open to most closed, and each rung adds a check.
First come first served assigns a value to the first qualified request. The qualification is usually that the request names a point of contact and a brief description, and there is no review of technical merit. This is the policy for values where collision is the only risk and where the meaning is self-evident from the name. It is fast and it is cheap, and it provides no assurance that the feature is well designed. It also provides no way to mark a value as one that must be understood, so a registry using this policy is implicitly relying on unknown-field handling to make the values safe to receive.
Specification required assigns a value only when a stable, publicly available specification exists. The specification need not be an RFC; it can be a document from another standards body or a vendor’s published document. The check is that the document exists and is permanent enough to be referenced. This is the policy for values where interoperability depends on a shared definition, which is most values.
Expert review assigns a value after one or more designated experts judge the request against criteria stated in the registry’s definition. The criteria are usually about clarity, uniqueness, and whether the feature belongs in this protocol at all. The check is judgement rather than document existence, which makes it more flexible and less predictable. A rejected request has no appeal beyond the working group that appointed the expert.
IESG approval and standards action are the closed end. The former requires the Internet Engineering Steering Group to approve, which effectively means a working group and a document; the latter requires a standards-track RFC. These are for values that change the protocol’s behaviour in ways that affect everyone, such as a new transport, a new address family, or a new version.
The ladder is not a quality ranking. A protocol that puts everything behind standards action will evolve slowly and will accumulate unregistered extensions. A protocol that puts everything behind first come first served will accumulate junk values and will eventually have to deprecate them. The usual design is to place the values that affect interoperability on the middle rungs and to keep the high rungs for the small set of decisions that cannot be reversed.
Sizing the space is a one-time decision
The identifier width sets the maximum number of values, and the allocation policy determines how fast they are consumed. The product of the two is the protocol’s expected lifetime before the namespace is exhausted, and it is worth computing at design time.
A one-byte space with 256 values, minus reserved and private ranges, leaves perhaps 200 allocatable values. If a protocol allocates ten values a year, the space lasts twenty years, which is roughly the lifetime of a successful protocol. If it allocates thirty a year, it lasts seven. TLS extension types are two bytes and have been allocated for well over a decade without approaching exhaustion; HTTP/2 settings identifiers are two bytes and are allocated sparingly. DNS record types are two bytes and were exhausted in practice long before the numeric limit, because the allocation policy was permissive and the space was used for many experimental types.
The interesting failure is not numeric exhaustion but semantic exhaustion. A space with a thousand values can still become unusable if the allocated values are poorly specified, because a receiver has to implement each one it wants to support and the cost of support grows with the number of values. A protocol with five hundred extension types is one where no implementation supports all of them, and interoperability becomes a matter of matching capability sets rather than implementing a specification.
The design response is to group related functions into one extension with internal structure rather than allocating a value per function. That keeps the registry small and pushes the versioning problem down a level, where it is the extension’s own problem. The cost is that the extension becomes a protocol in miniature, with its own extension points and its own ossification risk.
Private use, experimental, and the value of a sandbox
A private-use range is a block of values that the specification declares will never be allocated publicly. Implementations may use them for anything, and the specification states that a receiver must not assume any meaning for them. This is the sandbox.
The sandbox has two purposes. The first is experimentation: an implementer can try a feature without a registration, and if it works the feature can be brought to a registry with a public value. The second is vendor-specific behaviour: a product can extend the protocol for its own endpoints without colliding with anyone.
Both purposes depend on the private range being genuinely private, which means it must be large enough that a vendor can pick a sub-range without coordinating with other vendors. A private range of eight values is useless, because two vendors will collide. A range of 256 or more allows a vendor to pick a block and use it consistently.
The experimental convention is different: RFC 3692 describes how to designate experimental values and how to use them, with the requirement that an experimental value not be deployed as a permanent feature. The distinction from private use is intent rather than mechanism. An experimental value is expected to be replaced; a private value is expected to persist within a closed deployment.
The risk with both is leakage. An experimental value that ships in a product and is used by real deployments becomes de facto permanent, and the registry then has to decide whether to allocate it formally or to break the deployments. The formal allocation is usually the cheaper choice, which means the experimental range slowly fills with values that were never meant to be permanent. That is a policy failure, not a technical one, and the mitigation is to make the formal path fast enough that experiments do not need to leak.
Reading a registry as a design history
A registry is a record of what the protocol’s designers thought would be needed, and the divergence between the record and the actual allocations is informative. A registry with many allocated values in a category that the original specification did not anticipate indicates a design gap. A registry with a large reserved block that has never been used indicates either foresight or an extension point that was stillborn.
The TLS signature algorithm registry is a case where the initial set was small and the additions were driven by cryptographic necessity rather than by feature requests. The additions were constrained by the requirement that both endpoints support them, so the registry grew alongside the deployed base rather than ahead of it.
The HTTP method registry is the opposite: it is small, and the space has been used sparingly because adding a method changes the meaning of every resource. The constraint is semantic rather than numeric. A method that a client sends and a server does not implement cannot be ignored in the way an unknown header can, because the client’s intent is not recoverable from the request itself.
The DNS record type registry shows the cost of a permissive policy in a protocol where a type describes the structure of the data rather than an optional behaviour. The registry accumulated types for services that were never widely deployed, and a resolver that does not recognise a type must still carry it through correctly rather than treating it as an error, which is a requirement the specification has had to state explicitly. The type space is large, so the pressure is not numeric; it is that every type an implementation does understand is code it must maintain, and the cost of that maintenance accumulates whether or not the type is ever seen on the wire.
The pattern across all three is that the registry’s growth rate is set by the cost of supporting a value, not by the cost of allocating one. Allocation is cheap and support is expensive, so a protocol that makes support expensive will have a small effective namespace regardless of how many values it defines. That asymmetry is the reason allocation policy matters: it is the only lever that controls the rate at which support obligations are created.
What a value costs the receiver
Each allocated value is a branch in a parser and a decision in a state machine. The branch itself is cheap; the decision is not, because it usually requires a test, a fallback, and a way to report the absence of support. A protocol with a hundred values has a hundred such decisions, and the code that implements them is where most of the interoperability bugs live.
This is why specifications increasingly define a small set of values as mandatory to implement and the rest as optional. The mandatory set is the interoperability floor: two implementations that conform to it can talk to each other. The optional set is the extension surface: implementations that share an interest in a feature can use it. The floor keeps the protocol usable; the surface keeps it alive.
Defining the floor is a political act, because a value in the floor is one every implementation must build and test forever. The usual compromise is to keep the floor minimal and to add to it only when a value becomes so widely deployed that its absence breaks connectivity. That is a lagging indicator, and it means the floor is always behind the deployed reality.
The registry and the floor together are the protocol’s constitution. Changing either changes what implementations must do, and neither can be changed quickly. The mechanisms that let a protocol change without amending its constitution are the subject of extension negotiation without a version bump, which trades the certainty of a registry for the speed of an in-band agreement.
References
- RFC 8126: Guidelines for Writing an IANA Considerations Section in RFCs — IETF
- RFC 3692: Assigning Experimental and Testing Numbers Considered Useful — IETF
- RFC 6890: Special-Purpose IP Address Registries — IETF
- RFC 9110: HTTP Semantics — IETF
- RFC 1035: Domain Names - Implementation and Specification — IETF