Backward Compatibility Rules
OpenAPI
There are a few simple rules, and a couple of exceptions.
- Requests: do not add mandatories (e.g. adding a new mandatory field, making an optional field mandatory)
- Responses: do not remove mandatories (e.g. remove a mandatory field, make a mandatory field optional)
- Do not change value types (e.g. int to string)
Requests
Do not add mandatory keys and / or make values non-nullable for existing keys.
| Operation | Verdict | Reason |
|---|---|---|
| Add a mandatory key | incompatible | Existing consumers must send a key that they were not sending before. |
| Add an optional key | compatible | Existing consumers are not sending this key anyway, but new consumers may do so. |
| Remove a mandatory key | compatible | Consumers can send the key but server will henceforth ignore it. |
| Remove an optional key | compatible | If consumers choose to send the key, the server will now ignore it. |
| Optional key becomes mandatory | incompatible | Consumers who were not sending this key before will now be expected to send it. |
| Mandatory key becomes optional | compatible | Consumers who were sending this key before can either continue sending it or stop sending it. |
Responses
Do not remove mandatory keys and / or make values nullable for existing keys.
| Operation | Verdict | Reason |
|---|---|---|
| Add a mandatory key | compatible | Older consumers were not expecting this key and will ignore it. |
| Add an optional key | compatible | Older consumers were not expecting this key and will ignore it. The server may or may not send it, and consumers should be prepared for either. |
| Remove a mandatory key | incompatible | Older consumers were expecting this key, but henceforth the response will not contain it. |
| Remove an optional key | compatible | In some cases, the server used to send this in the response. Henceforth it never will. |
| Optional key becomes mandatory | compatible | Sometimes the server didn't send this key. But henceforth, the server will always send this key. Consumers who ignored it before can continue doing so. Consumers who checked for it before have code to handle it. |
| Mandatory key becomes optional | incompatible | It's possible that the server will not send this key. Some consumers may be expecting it, but will not be receiving it henceforth. |
AsyncAPI
For AsyncAPI all of the above rules apply based on this mapping:
- Requests map to received messages handled by an
action: receivetype operation. - Responses map to messages sent by a
reply,x-specmatic-retry,x-specmatic-dlq, or anaction: sendoperation.
In addition, the following rules apply:
| Operation | Verdict | Reason |
|---|---|---|
| Remove an existing operation | incompatible | Existing clients or services still depend on that operation. |
Change an operation's action | incompatible | The interaction changes from receive to send, or vice versa. |
Change an operation's channel address | incompatible | Existing producers or consumers will continue using the old topic. |
Remove a reply from a request-reply operation | incompatible | Existing callers still expect the reply message. |
Change the reply channel address | incompatible | Existing callers will continue listening on the old reply topic. |
Remove x-specmatic-retry | incompatible | Existing retry behavior is broken. |
Change the x-specmatic-retry channel address | incompatible | Existing retry consumers will continue using the old retry topic. |
Remove x-specmatic-dlq | incompatible | Existing dead-letter behavior is broken. |
Change the x-specmatic-dlq channel address | incompatible | Existing DLQ consumers will continue using the old DLQ topic. |
Change a message correlationId.location | incompatible | Existing correlation logic will read the correlation ID from the old location. |
Remove a correlationId from a sent message | incompatible | Existing consumers need it to correlate replies, retries, or DLQ messages. |
| Add a new operation | compatible | Existing clients and services can ignore it. |
| Rename an operation | compatible | The action, topic, reply topic, and message contract are unchanged. |
| Rename a message reference without changing the resolved message schema | compatible | The message contract seen on the wire is unchanged. |
Rename a correlationId reference without changing its resolved location | compatible | Correlation still uses the same message location. |
Remove a correlationId from a received message | compatible | The receiver no longer requires that correlation ID and will ignore it |