Handling Backward Compatibility
1. Adding New Fields Safely
| Rule | Detail |
|---|---|
| Pick new tag | Unused number — never reuse |
| Default behavior | Old clients ignore unknown fields |
| Don't change semantics | Of existing fields |
2. Deprecating Fields
Example: Deprecated option
message User {
string name = 1 [deprecated = true];
string display_name = 4;
}
| Step | Detail |
|---|---|
| Mark deprecated | Codegen warns on use |
| Document replacement | In proto comment |
| Remove later | Only after all clients migrated |
3. Reserving Field Numbers
4. Versioning Services
| Strategy | Detail |
|---|---|
| Package version | user.v1, user.v2 |
| Run side-by-side | Until v1 deprecated |
| Avoid in-place breaking change | Always cut new version |
5. Handling Schema Evolution
| Change | Safe? |
|---|---|
| Add optional field | Yes |
| Remove field | Reserve number — yes |
| Change type | No (mostly) |
| Rename field | Yes (wire uses number) — bad for JSON consumers |
| Change cardinality | Repeated ↔ singular: NO |
6. Using Buf Breaking Detection
| Category | Detail |
|---|---|
| FILE | Strict — any file change risky |
| PACKAGE (default) | Same package compat |
| WIRE | Only true wire-breaking |
| WIRE_JSON | Wire + JSON name compat |
7. Maintaining API Compatibility
| Practice | Detail |
|---|---|
| Contract tests | Old client × new server in CI |
| Schema registry | Central .proto with PR review |
| Long deprecation | Min one release cycle |
8. Migrating Clients
| Step | Detail |
|---|---|
| Dual-publish | v1 and v2 simultaneously |
| Adapter layer | Server proxies v1 → v2 internally |
| Feature flag | Toggle client version |
9. Supporting Multiple Versions
| Pattern | Detail |
|---|---|
| Side-by-side services | Register both on same server |
| Shared business core | Both wrap same domain layer |
| Sunset header | Communicate end-of-life date |
10. Sunsetting Old Versions
| Phase | Detail |
|---|---|
| Announce | Sunset header + docs |
| Warn | Log per-call deprecation |
| Block 0%/10%/100% | Gradual rollout of unavailability |
| Remove | Delete package; cannot be undone |