Modular monolith or microservices: choosing on team shape
Microservices solve organisational scaling problems and introduce distributed systems problems. Most teams should start with a well-structured monolith.
Versioning is a policy question before it is a technical one. Decide what breaking means and how long you support old versions.
Additive changes — new optional fields, new endpoints — are generally safe if consumers ignore unknown fields, which is worth stating in your documentation as an expectation.
Removing a field, renaming one, changing a type, tightening validation or changing the meaning of a value all break consumers. Tightening validation is the one most often overlooked, because it looks like a fix.
The mechanism matters less than applying it consistently and documenting it clearly.
Publish how long a version is supported once its successor ships. Announce deprecation in advance, return a deprecation header on affected responses, and monitor which consumers are still calling it.
Contacting the remaining consumers directly is what actually completes a migration. Silence followed by removal produces incidents.
Every supported version is code to maintain and test. Design defensively so most changes are additive, and reserve new versions for genuine breaks.
Two supported versions is manageable. Five is a maintenance problem that will eventually force an abrupt removal.
Technical versioning mechanisms only work if consumers know what is happening. Most breakage after a version change traces to communication rather than to the mechanism.
Publish a changelog, provide a migration guide with before-and-after examples, and give a realistic timetable. Where you can identify consumers from access logs, contact them directly rather than relying on announcements being read.
Monitor usage of deprecated versions and follow up with the remaining callers. Removal on a date with active consumers still calling produces an incident that was entirely predictable.
Long enough for consumers to migrate reasonably commonly six to twelve months for external APIs, less for internal ones where you know every consumer.
A lighter form. Knowing every consumer allows coordinated changes, but a compatibility policy still prevents surprise breakage during independent deployments.
GraphQL favours evolution over versioning: add fields, deprecate old ones, and use field usage data to know when removal is safe.
Keep reading
Microservices solve organisational scaling problems and introduce distributed systems problems. Most teams should start with a well-structured monolith.
Relational databases handle the overwhelming majority of business workloads well. Alternatives should be chosen for specific reasons.
Complete rewrites fail at a high rate. Incremental strangulation delivers value earlier and carries far less risk.