Semantic versioning
Semantic Versioning (SemVer) - a contract on how the version number reflects the nature of the changes. Format: MAJOR. MINOR. PATCH[-PRERELEASE][+BUILD].
Meaning:- MAJOR - Incompatible changes (breaking).
- MINOR - reciprocally compatible features/extensions.
- PATCH - Backward Compatible Bug/Security Fixes.
Goal: predictable evolution of APIs, events, data schemas, SDKs and configs without sudden consumer breakdowns.
1) Convention numbers
X.Y.Z[-alpha.1 -rc.1][+build.sha]
Pre-release ('-alpha', '-beta', '-rc') - unstable assemblies; do not promise compatibility.
Build metadata ('+ sha') - does not affect the comparison order, useful for tracing.
Up to 1. 0. 0 Any change can be considered breaking (but it is better to follow the rules from the very start).
2) What to consider breaking/minor/patch
PATCH (Z):- Fixes for bugs and security without changing the contract.
- Docking updates that do not affect the contract.
- Optimization without changing responses/events/schemes.
- Add new optional fields/methods/endpoints.
- Extending enum values if consumers tolerate unfamiliar values.
- New database indices, nullable columns with default, new events in addition to the old ones.
- Deleting/renaming fields, changing types, mandatory.
- Change semantics/statuses/error codes.
- Changing serialization format, key scheme, transport protocol.
- Compress/merge topics, transfer the meaning of the event, change the partitioning scheme.
- Database migrations that require "two-phase" switching without backward compatibility.
3) Artifact versioning
3. 1 REST
Variants: 'URI/v1/...', headers ('Accept: application/vnd. acme. game+json; version = 1 '), parameter.
Recommendation: version in URI for public APIs; for internal - through the header c negotiation.
MINOR: add optional fields, new filters/resources; do not change existing answers.
PATCH: fixes, definition refinement, stable sorting.
3. 2 gRPC
Changing MAJOR → signatures/types (new package/service: 'acme. wallet. v2`).
New fields - labeled optional; the server must ignore the unknown.
We do not delete the fields: "depricket + reserve a number," delete - only in the next MAJOR.
3. 3 GraphQL
MINOR: new fields/types/query; removal - through '@ deprecated' + migration window, full removal - MAJOR.
Change nullable→non -nullable - MAJOR.
3. 4 Events and Topics (Kafka/SQS)
Schemas in Schema Registry: evolution of additive (add fields with defaults).
New incompatible version → new subject/topic ('bet. settled. v2`).
The partitioning key is immutable within MAJOR.
3. 5 DB diagrams
"Expand, then fold":1. Add a column (nullable/default) →
2. Fill in the backfill →
3. Translate → Reads
4. Remove old (MAJOR only).
Change type/PK/uniqueness - MAJOR, under the phicheflag and double entry.
3. 6 SDK/CLI
Public methods/signatures are the same rules.
For autogeneration (OpenAPI/Proto) - version of the batch name and artifacts.
4) Deprivation policy and life cycle
Each breaking change is preceded by depriction (usually 90-180 days for external, 30-60 for internal).
Communications: changelog, e-mail/webhooks to partners, banners in the developer portal.
Dual-run mode: keep 'v1' and 'v2' in parallel, monitor the share of traffic 'v1'.
Sunset headers (REST): `Sunset: 2026-03-31`, `Link: <url>; rel="deprecation"`.
5) Version negotiation
The client sends the desired version + the maximum supported version (for example, 'Accept-Version: 1,2').
The server responds with'Content-Version: 2'if it can promote.
In bidirectional protocols (WebSocket, gRPC) - exchange of Hello frames with 'supported _ versions'.
6) Provider Adapter Integration (ACL)
The external provider changes the scheme - inside the adapter we keep the v1/v2 mappers and release MINOR for the internal event, keeping our domain contract.
If external changes make their way inside, this is the MAJOR of our domain event and a new subject.
7) Changelog and commit labels
Follow Keep a Changelog and Conventional Commits:- `feat:...` → MINOR
- 'fix:... '/' chore ',' docs', 'perf' (no contract) → PATCH
- 'feat!: '/' fix!: '/' refactor!: 'or' BREAKING CHANGE: 'in MAJOR → body
[2.3.0] - 2025-10-31
Added
- GET /v1/games?capabilities=jackpot (optional)
Changed
- GraphQL: field Game.volatility @deprecated, use Game.riskProfile
8) Release automation
CI: circuit validators (OpenAPI/Protobuf/Avro/JSON-Schema), breaking-diffuse detect. more
SemVer-bot: analysis Conventional Commits → calculates bump (major/minor/patch), puts a tag, generates a changelog.
CD: separate deploy and release (phicheflags/configs activate the new version).
Control: do not publish 'latest' on PRO until successful canary and agreed SLOs.
9) Semantics for configurations and policies
Configs (YAML/JSON) also have a schema version: 'schema _ version: 3'.
MINOR - new optional fields/rules MAJOR - change of structure/obligation.
v2/v3 support in validator; config migrator with incompatibility report.
10) Compatibility testing
Consumer-driven contract tests (Pact): per integration.
Schema-evolution tests: run old payloads on a new schema and vice versa.
Replay - Plays the production traffic 'v1' to 'v2' in shadow.
Property-based: resistance to unfamiliar fields/enum.
11) Observability by version
Tag metrics/logs: 'api _ version', 'schema _ version', 'event _ version'.
Migration dashboards: traffic share by versions, error/latency by 'v1/v2'.
Alerts: if 'v1' does not go down as planned; 4xx/5xx growth after 'v2' release.
12) Migration patterns without downtime
Expand → Migrate → Contract (БД).
Dual write + compare divergences before switching reading.
Shadow compare for ranking/rules.
Canary by tenant/region; feature flags for quick rollbacks.
Read-compat/Write-compat windows: the new version reads old data, but writes in a new format.
13) Anti-patterns
"Version in each field" instead of versioning the resource/event.
Hidden breaking changes under MINOR (for example, changing defaults).
Removal of depricated without window and consumption metrics.
"Forever v1": no plan to remove old versions of → technical debts and vulnerabilities.
Mix the business version and the container image version.
14) Versioning Policy Checklist
- Fixed version format and sources of truth (Registry/Portal).
- Approved list of breaking criteria by artifacts (REST/gRPC/GraphQL/events/DB).
- Deprications process: timing, communications, sunset/banners, dual-run.
- Automatic diff checker and Conventional Commits.
- Version and alert consumption dashboards.
- Migration playbooks (expand/migrate/contract, dual-write, shadow).
- Configs and SDKs have their own versions and case.
- Documentation "how to choose a version" for clients and "how to upgrade" for teams.
15) Examples of versioning (iGaming cases)
'BetSettled v1'event →' v2 ': added' void _ reason '(optional) and' tax. amount` (optional) — MINOR. Renamed 'payout'→'win_amount' - MAJOR, a new subject.
REST '/wallets/transfer ': added filter'? tenant _ id = '- MINOR. Changed error code '409'→'422' - MAJOR.
GraphQL: marked'Player. age 'as' @ deprecated 'in favor of' Player. ageGroup '- release in MINOR, deletion in MAJOR after period X.
DB: added column 'bonus _ wager _ left' nullable - MINOR. Made non-null and deleted 'bonus _ left' - MAJOR (via expand/contract).
Conclusion
Semantic versioning is not about numbers, but about trust and predictability. Clear rules, automated checks, controlled deprictions, and transparent telemetry allow APIs, events, and pain-free schemas to evolve for integrations - and release changes frequently, safely, and meaningfully.