Adding new required fields to an existing message type is a backwards-incompatible change, because old servers won't ever send that field.
Adding a whole new message type with required fields is backwards-compatible, because old servers won't be sending that message at all. For example, say we start with:
message Old {
required int32 i = 1;
}
Then we add a new message:
message Old {
required int32 i = 1;
optional New m = 2;
}
message New {
required string s = 1;
}
This is backwards-compatible. When an old program sends a message to a new program, the field m
will be absent, which is fine because it is optional. The required field m.s
is only required if m
itself is present.
When a new program sends a message to an old program, the field m
will be ignored. required
does NOT mean that the receiver can't ignore it. required
only means that the sender is required to send it.
Note that I strongly recommend against using required
. Proto3 removed required
, and Cap'n Proto never had it in the first place, because of the unexpected problems it can cause. Here's an in-depth discussion I wrote.
(Disclosure: I'm the author of Proto2 and Cap'n Proto.)