Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
25 Jul 2025 · 7 min read ·Article 47 / 110
Go

47 Reserved Fields and Reserved Numbers

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

In the world of software engineering—especially when developing communication protocols, data serialization, and API design—the terms reserved fields and reserved numbers come up quite often. Although at first glance they may sound like “leaving slots empty” with no real purpose, both play a strategic role in maintaining compatibility and enabling the evolution of a system.

This article breaks down the concepts of reserved fields and reserved numbers in depth—complete with code examples, a simple simulation, and a discussion of their strategy in professional software engineering.


1. What Are Reserved Fields and Reserved Numbers?

Reserved Fields

Reserved fields are parts of a data structure (packet, message, struct, and so on) that are skipped over—in other words, set aside for future use. These fields have no meaning right now, must be ignored by the receiver, yet are still preserved within the structure.

Example situations:

  • A new protocol is about to be born, but its design is expected to evolve.
  • You want to extend something without breaking compatibility (backward/forward compatible).

Reserved Numbers

Reserved numbers are specific values/numbers within a field (typically an enumeration or message type) that are reserved—not used now, but designated for a future revision.
They can also mean that certain numbers must not be used by custom implementations (reserved for internal use).


2. Why Are Reserved Fields and Numbers Important?

Here is a concise table summarizing the reasons for using both:

GoalReserved FieldsReserved Numbers
Compatibility✔︎✔︎
Future-proofing✔︎✔︎
Avoiding conflicts✔︎
Speeding up revisions✔︎✔︎

  • Compatibility: So that new and old systems can keep “talking” to each other.
  • Future-proofing: Ensures the structure/protocol stays relevant years down the line.
  • Avoiding conflicts: For certain assigned enums/IDs, reserved numbers prevent duplicated meanings across implementations.
  • Speeding up revisions: Allows new features to be added without overhauling the entire system.

3. A Concrete Example: Reserved Fields in a Protocol

Let’s illustrate reserved fields in the design of a simple message format. Say you are designing a protocol for exchanging messages between an IoT Device and a Server.

Defining the Data Structure

go
 1// DevicePacket mirrors the C struct: device_packet_t
 2type DevicePacket struct {
 3	MessageType uint16    // 2 bytes
 4	DeviceID    uint32    // 4 bytes
 5	Status      uint8     // 1 byte
 6	Reserved    [5]byte   // 5 bytes
 7	Timestamp   uint32    // 4 bytes
 8}
 9
10// Encode converts a DevicePacket to []byte (big-endian)
11func (p *DevicePacket) Encode() ([]byte, error) {
12	buf := new(bytes.Buffer)
13	err := binary.Write(buf, binary.BigEndian, p)
14	return buf.Bytes(), err
15}
16
17// Decode converts []byte back into a DevicePacket
18func Decode(data []byte) (*DevicePacket, error) {
19	var p DevicePacket
20	buf := bytes.NewReader(data)
21	err := binary.Read(buf, binary.BigEndian, &p)
22	return &p, err
23}

Note: reserved[5] will likely be filled with 0x00 by the sender, but the receiver must still read and ignore this field.

The Send and Receive Flow

MERMAID
flowchart LR
    Start -->|Isi struct| Sender[Device]
    Sender -->|Isi reserved = 0| Packet
    Packet -->|Serialisasi| Network
    Network -->|Deserialisasi| Receiver[Server]
    Receiver -->|abaikan reserved| ProsesData

Simulation code (Python mock):

go
 1package main
 2
 3import (
 4	"bytes"
 5	"encoding/binary"
 6	"fmt"
 7	"log"
 8)
 9
10func encodePacket(messageType uint16, deviceID uint32, status uint8, timestamp uint32) []byte {
11	buf := new(bytes.Buffer)
12
13	// Write according to order and endianness
14	binary.Write(buf, binary.BigEndian, messageType)
15	binary.Write(buf, binary.BigEndian, deviceID)
16	binary.Write(buf, binary.BigEndian, status)
17	buf.Write(make([]byte, 5)) // reserved 5 zero bytes
18	binary.Write(buf, binary.BigEndian, timestamp)
19
20	return buf.Bytes()
21}
22
23func decodePacket(data []byte) (messageType uint16, deviceID uint32, status uint8, timestamp uint32, err error) {
24	buf := bytes.NewReader(data)
25
26	if err = binary.Read(buf, binary.BigEndian, &messageType); err != nil {
27		return
28	}
29	if err = binary.Read(buf, binary.BigEndian, &deviceID); err != nil {
30		return
31	}
32	if err = binary.Read(buf, binary.BigEndian, &status); err != nil {
33		return
34	}
35	reserved := make([]byte, 5)
36	if _, err = buf.Read(reserved); err != nil {
37		return
38	}
39	if err = binary.Read(buf, binary.BigEndian, &timestamp); err != nil {
40		return
41	}
42	return
43}
44
45func main() {
46	// Simulation
47	packet := encodePacket(1, 12345, 2, 1721548800)
48
49	mt, did, st, ts, err := decodePacket(packet)
50	if err != nil {
51		log.Fatal(err)
52	}
53	fmt.Printf("type=%d, device=%d, status=%d, ts=%d\n", mt, did, st, ts)
54}

4. Reserved Numbers: An Enum & Protobuf Case Study

In protobuf, you’ll often come across the reserved keyword, used either for field numbers or names. This is crucial so that future revisions don’t cause unwanted overwrites (a breaking change).

Enum Example with Reserved Numbers

protobuf
1enum UpdateStatus {
2    UNKNOWN = 0;
3    PENDING = 1;
4    COMPLETED = 2;
5
6    // Reserved for future use
7    reserved 100 to 199;
8}

If a new status is added to the protobuf definition later, you simply assign it a number from the reserved block. On top of that, reserved numbers prevent external developers from populating that enum with values in the 100–199 range (in plugins or custom distributions), keeping the protocol’s integrity intact.

Simulating an Error When Violating a Reservation

protobuf
1// This will error out!
2enum UpdateStatus {
3    UNKNOWN   = 0;
4    RESERVED2 = 120; // <--- Error, falls within the reserved block
5    reserved 100 to 199;
6}

The protobuf compiler will throw an error, keeping the implementation disciplined.


5. Reserved Fields in APIs & JSON

Reserved fields aren’t limited to protocols or binary formats—they are frequently adopted in JSON-based REST APIs as well.

Response format:

json
1{
2  "result": "ok",
3  "device_id": 12345,
4  "reserved": null
5}

The documentation notes: “The ‘reserved’ field may be ignored, but it must be included for forward compatibility.”

The benefit? When v2 is released, that field can start carrying new meaning without major changes on the part of older clients or servers.


6. Reserved Fields/Numbers in the Real World

TCP/IP Options:
The TCP packet header contains a 6-bit ‘Reserved’ field. The RFC instructs that its value be 0 and that it be ignored by the receiver—ready to be used for future options (and to this day, some of it has in fact never been used).

HTTP Headers:
Many custom headers used to be prefixed with ‘X-’, which then became a convention marking a reserved area for vendor headers, before they were standardized.


7. Best Practices for Reserved Fields & Numbers

  1. Always fill reserved fields with their default value (zero/NULL).
    Whoever fills the field must remain disciplined even when the field is unused.

  2. Don’t assign any meaning to reserved entries in the current version.
    The explanation in the documentation and comments must be explicit:

    // reserved, do not use - for future compatibility

  3. Use reserved numbers to “block” external/plugin abuse.
    For example: enum 0–100 for the core protocol, 200–250 reserved for internal experimental/extension use.

  4. Documentation is mandatory.
    Without documentation, a reserved field/number only ends up confusing the next developer.


Conclusion

Reserved fields and reserved numbers are a mature strategy for keeping protocols, APIs, and data systems scalable and compatible into the future. Like setting aside an empty plot of land next to your house, reserved fields make expansion possible without disturbing the existing structure.

As engineers, discipline and transparency in maintaining reserved spots are part of a healthy engineering culture—good for the next version, and good for the generation of developers yet to come.


References


I hope this article helps you design protocols or APIs that are built to last.

Related Articles

💬 Comments