What happens when interfaces change
Interfaces change.
They always do.
The real question is not whether interfaces will evolve, but how safely and predictably that evolution happens—especially when interfaces are consumed by multiple teams and services.
Graftcode is designed so that interface changes are:
- explicit
- visible early
- and safe to adopt incrementally
Public interfaces behave like shared libraries
The most important mental model to keep in mind is this:
Note
A public interface exposed through Graftcode behaves like a shared library API.
Consumers:
- install it as a dependency
- rely on its types
- discover changes through tooling
This is a very different model from traditional remote APIs, where changes are often discovered only at runtime.
Evolutionary changes are the default
Graftcode encourages evolutionary changes rather than breaking ones.
Typical evolutionary changes include:
- adding new methods
- introducing optional parameters
- adding overloads
- extending return types in a compatible way
In these cases:
- existing Grafts continue to work
- existing consumers do not break
- newer consumers gain additional capabilities
No coordination is required.
Breaking changes are explicit
Sometimes breaking changes are unavoidable.
In Graftcode, breaking changes are never silent.
When a public interface changes incompatibly:
- a new version of the Graft is produced
- older Grafts remain available
- consumers must explicitly choose to upgrade
There is no scenario where a consumer suddenly starts calling a different interface without noticing.
What developers see when something changes
Because Grafts are strongly typed dependencies, developers discover changes immediately.
Depending on the change, they may see:
- new methods appearing in autocomplete
- new optional parameters
- compilation errors if required parameters were introduced
- renamed or removed members failing to compile
The IDE becomes the primary feedback mechanism.
There is no need to inspect changelogs or compare schemas.
Automatic updates and CI feedback
Teams often configure their dependencies to allow automatic updates within compatible version ranges.
In this setup:
- CI pipelines pull newer Grafts automatically
- unit and integration tests validate compatibility
- failures are detected early in the pipeline
This shifts the cost of change from production incidents to build-time feedback.
Planned: automatic breaking change detection (roadmap)
One natural extension of the Unified Graft Model is the ability to compare interface versions structurally, not just syntactically.
Graftcode is designed so that each exposed module produces a Unified Graft Model (UGM).
This opens the door to detecting breaking changes automatically by comparing successive versions of the same module.
Detecting breaking changes at interface level
By comparing two UGM versions of the same module, it becomes possible to detect changes such as:
- removed public methods
- renamed methods or parameters
- removed or renamed return types
- changes to required parameters
- incompatible type changes
These are the same kinds of breaking changes developers already try to avoid in shared libraries—but detected automatically and consistently.
Warnings at Gateway startup
A planned capability is for the Graftcode Gateway to analyze interface evolution when a module is started.
If a new version of a module introduces breaking changes compared to a previous version, the Gateway could:
- detect the breaking changes automatically
- emit clear warnings at startup
- indicate which methods or signatures are incompatible
This makes breaking changes visible immediately, at the point where they are introduced.
Warnings for incompatible Grafts at runtime
Another planned capability is runtime awareness of incompatibility.
If an older Graft communicates with a Gateway hosting a newer, incompatible interface, the system could:
- detect that the Graft was generated from an older UGM
- identify which methods are now incompatible
- emit warnings on the caller side
These warnings could indicate:
- which methods are no longer compatible
- that calling them will result in failure
- that the consumer should upgrade its Graft
This shifts discovery of breaking changes from runtime failures to early, actionable warnings.
CI/CD enforcement before deployment
Beyond runtime warnings, this mechanism enables tooling for build pipelines.
A planned tool could:
- run during CI/CD for modules intended to be hosted on a Gateway
- compare the new UGM with the previously published version
- fail the build if breaking changes are detected
This would allow teams to:
- enforce interface stability automatically
- catch breaking changes before deployment
- treat public interfaces with the same discipline as shared libraries
Breaking changes would become a deliberate decision, not an accidental outcome.
Why this matters
This approach reinforces the core idea behind Graftcode:
Note
Remote interfaces should be treated with the same rigor as shared code.
By detecting breaking changes at the interface-model level:
- teams gain earlier feedback
- consumers are protected from surprise failures
- interface evolution becomes intentional and observable
This turns interface stability into an automated property of the system, not a matter of convention.
Roadmap note
These capabilities are part of the planned evolution of the Graftcode tooling and build-time ecosystem.
They build directly on:
- the Unified Graft Model
- strong typing
- explicit public interfaces
and are a natural next step in making distributed systems behave like well-managed codebases.
Older and newer Grafts can coexist
Different consumers can use different Graft versions at the same time.
This allows:
- gradual migration
- independent release cycles
- reduced coordination overhead
As long as older interfaces remain available, existing consumers continue to work unchanged.
Knowing when it is safe to remove old interfaces
Over time, some interfaces become unused.
When Gateways are connected to a project, aggregated usage information can show:
- which Grafts are still in use
- which versions are active
- which interfaces have no remaining consumers
This makes it possible to:
- deprecate interfaces confidently
- remove unused versions safely
- avoid breaking unknown consumers
Versioning through facade classes
A common pattern for managing change is to version facade classes.
For example:
OrdersV1OrdersV2
Each class represents a stable public contract, while internal business logic evolves freely.
Graftcode does not enforce this pattern, but it aligns naturally with the programming model and makes intent explicit.
Relaxed versioning for experimentation
During early development or experimentation, teams may choose relaxed versioning.
In this mode:
- incompatible changes result in uniquely identified Grafts
- conflicts are avoided automatically
- experimentation is unblocked
This is useful when interfaces are still fluid and consumers are few.
Why this model works
This approach works because:
- interfaces are explicit
- changes are visible at development time
- consumers control upgrades
- tooling provides immediate feedback
Distributed systems start behaving like evolving codebases—not brittle integrations.
In short
When interfaces change in Graftcode:
- changes are explicit and versioned
- older consumers continue to work
- newer consumers opt in deliberately
- IDEs and CI pipelines surface issues early
Interface evolution becomes a managed process, not a source of risk.
See also: Alpha limitations and known constraints