API Versioning
APIs do not fail when they are wrong.
They fail when they change unexpectedly.
Once an API is consumed by:
- Frontends
- Mobile apps
- Third-party services
- Partners
- Automation scripts
It becomes a contract.
Plumego does not impose an API versioning strategy — deliberately.
But it enforces constraints that make good versioning strategies possible.
This document explains how to evolve APIs explicitly, safely, and predictably.
First Principle: Versioning Is a Contract Decision
API versioning is not a routing trick.
It is a contract and communication decision.
If you treat versioning as:
- A convenience
- A refactor aid
- A framework feature
You will break clients.
In Plumego’s worldview:
Versioning decisions live at the boundary — where contracts are defined.
When You Actually Need a New Version
You need a new API version when you introduce:
- Breaking request/response shape changes
- Semantic changes to behavior
- Different authorization rules
- Different validation rules
- Different error semantics
You do not need a new version for:
- Adding optional fields
- Adding new endpoints
- Improving internal performance
- Refactoring internal code
Backward compatibility is a discipline, not an accident.
Supported Versioning Strategies
Plumego supports all common strategies — explicitly.
1. Path-Based Versioning
Example:
/api/v1/orders
/api/v2/orders
Implementation:
- Separate route groups
- Separate handlers
- Possibly separate usecases
This is the most explicit and debuggable strategy.
Recommended for public APIs.
2. Header-Based Versioning
Example:
X-API-Version: 2
Accept: application/vnd.example.v2+json
Implementation:
- Pre-dispatch routing
- Explicit handler selection
- No hidden fallbacks
This strategy keeps URLs clean but increases routing complexity.
3. Host-Based Versioning
Example:
v1.api.example.com
v2.api.example.com
Implementation:
- External routing (gateway or server mux)
- Separate Plumego apps per version
This is operationally clean but infrastructure-heavy.
What Plumego Does Not Do
Plumego does not:
- Auto-negotiate versions
- Guess client intent
- Provide implicit fallbacks
- Inject versioning logic into handlers
- Rewrite responses silently
If a request hits a versioned handler,
it is because you routed it there explicitly.
Versioning and Routing Structure
A recommended structure for path-based versioning:
internal/
api/
v1/
orders/
handler.go
v2/
orders/
handler.go
Each version:
- Has its own handlers
- Owns its own contracts
- Can evolve independently
Shared logic should live below the API layer.
Versioning and Usecases
Important rule:
Do not version usecases unless behavior truly diverges.
Common pattern:
- One usecase
- Multiple handlers (v1, v2)
- Different request/response mapping
Only introduce versioned usecases when:
- Business semantics differ
- Authorization rules change
- Side effects change
Avoid duplicating business logic just to version APIs.
Deprecation Before Removal
Removing APIs without warning is hostile.
A responsible lifecycle:
- Introduce new version
- Mark old version as deprecated
- Communicate timelines clearly
- Monitor usage
- Remove only when safe
Deprecation is a process, not a flag.
Versioning and Error Semantics
Error responses are part of the contract.
Changing:
- Status codes
- Error formats
- Error meanings
Is a breaking change.
If error semantics change,
they must be versioned like any other behavior.
Documentation and Versioning
Every API version must have:
- Its own documentation
- Clear changelogs
- Explicit status (active / deprecated)
Plumego Docs should reflect versions explicitly.
Undocumented versions are operational debt.
Testing Versioned APIs
Testing must respect version boundaries:
- Separate handler tests per version
- Shared usecase tests where behavior is shared
- Regression tests for deprecated versions
- Contract tests for external consumers
Never assume “it still works” without tests.
Avoiding Version Explosion
Versioning has a cost.
Avoid creating new versions for:
- Minor field additions
- Internal refactors
- Performance improvements
Prefer additive changes whenever possible.
A small number of long-lived versions
is far healthier than many short-lived ones.
Anti-Patterns to Avoid
Silent Behavior Changes
Same endpoint, different behavior — without a version bump.
This is the fastest way to lose trust.
Version Logic Inside Handlers
if version == "v2" { ... }
This mixes contracts and logic and becomes unmaintainable.
“Latest” as a Version
“Latest” is not a contract.
It is a moving target.
Versioning and Multi-Service Systems
In multi-service setups:
- Each service versions independently
- Internal APIs still need contracts
- Version skew must be expected
Do not rely on synchronized upgrades.
Explicit versioning reduces coordination cost.
Summary
In Plumego:
- API versions are explicit contracts
- Routing makes version choice visible
- Handlers define version boundaries
- Usecases remain stable when possible
- Breaking changes are deliberate
- Clients are respected
API versioning is not about change —
it is about changing without betrayal.
Advanced Section: Complete
With API versioning covered, the Advanced section now forms a complete arc:
- Custom routing
- Embedding
- Multi-service setups
- Performance
- Component replacement
- Background processing
- API evolution
All without breaking Plumego’s core guarantees.
From here, the system is ready to live for years.