Looking for automated database schema migration safety? See our guide on Schema Migration Constraints.
The challenge
Consider a scenario where your team builds a feature in theconsumer service that calls a newly added endpoint in the provider service, which is maintained by a different team. For the feature to work in production, both services must be running compatible versions. Without automated constraint checking, you’d need to manually coordinate these deployments across teams and environments—a process prone to human error and potential outages.
Declaring dependencies
Ryvn has two kinds of dependencies. Different people declare them, in different files, to answer different questions.- Release dependencies say which versions of other services a release works with. A service’s owners declare them as version ranges in the service’s release metadata. They travel with the release to every environment, and Ryvn checks them whenever either side of the dependency upgrades.
- Installation dependencies say which installations must be ready before an installation first comes up, and which installation a release’s version range applies to. An environment’s owners declare them on the installation, or on a service inside a blueprint. They carry no version bounds and apply only in that environment.
web service that uses postgres:
web works with postgres 15.x.x and 16.x.x. The installation says that in production, web-production installs after postgres-main, and its postgres range is checked against postgres-main only.
Release dependencies are enough for the cross-team scenario above. Add installation dependencies when a new environment needs installations to come up in order, or when an environment runs more than one installation of a service.
Release dependencies
Release dependencies live in a service’s release file and are published with each release. For the full field reference, including version range syntax, see Service dependencies in the release metadata docs.Declaring a release dependency
Supposeconsumer is at version 0.8.0 and you’re building a feature for 0.9.0 that calls the new endpoint in provider 0.2.0. In the same change that adds the feature, add a dependency to the service’s release file:
consumer 0.9.0 to Ryvn. A release’s dependencies can’t be changed after it is published. To change a range, publish a new release.
Waiting for a dependency to upgrade
When Ryvn’s control plane sees theconsumer 0.9.0 release, it checks whether existing installations can safely upgrade. Consider an environment in this state:
consumer from 0.8.0 to 0.9.0, Ryvn asks:
Do the currently installed services meet the target release’s dependency constraints?
consumer 0.9.0 requires provider 0.2.0 to 0.x.x, and the environment runs provider 0.1.0.
Result: Ryvn holds the consumer upgrade until provider is upgraded to a version in that range.
Blocking a breaking upgrade
The check also runs in the other direction. Ryvn won’t upgrade a service if the new version falls outside the range of an installed service that depends on it. Start from the same environment, where the installedconsumer 0.8.0 release declares a dependency on provider with maxVersion: 0.x.x. The owners of provider release 1.0.0, which removes endpoints deprecated in 0.x.x. Before upgrading provider, Ryvn asks:
Will any currently installed services have dependency constraints violated by this upgrade?
1.0.0 is outside consumer’s 0.x.x range.
Result: Ryvn holds the provider upgrade until every installed consumer runs a release that accepts provider 1.0.0. To unblock it, publish a consumer release whose range covers both the running provider and the new one:
consumer 0.8.1 deploys against the running provider 0.1.0, and once it is installed, provider 1.0.0 can follow. A range that accepts only 1.x.x would deadlock: consumer would wait for provider 1.0.0, and provider 1.0.0 would wait for consumer.
Installation dependencies
Release dependencies don’t say which installation a release talks to, or in what order installations come up in a new environment. Installation dependencies cover both. Adddependencies to the installation:
dependencies on server, job, Helm chart, and Terraform installations.
Ordering the first install
Whenweb-production and postgres-main are declared in the same sync, postgres-main installs first. web-production waits with a dependency issue such as:
postgres-main is ready (UP_TO_DATE). A service: entry is satisfied by any ready installation of that service.
Installation dependencies hold only the first install. After that, web-production’s upgrades, configuration changes, and secret rotations deploy even while postgres-main is being reinstalled or has failed. Its release dependencies still apply as usual. Force deploys, rollbacks, retries, and version pins skip dependency checks, as they do for release dependencies.
Pointing a release range at one installation
Take theweb release from above, which requires postgres 15.0.0 to 16.x.x. Production runs two postgres installations: postgres-main, which web uses, and postgres-analytics, which it doesn’t. With release dependencies alone, the range applies to both, so upgrading postgres-analytics to 17.0.0 is blocked even though web never talks to it.
When web-production names postgres-main, its release range is checked against postgres-main only, in both directions:
- Upgrading
postgres-analyticsto17.0.0proceeds. - Upgrading
postgres-mainto17.0.0is blocked: web-production’s own deploys wait ifpostgres-mainis out of range or not ready, even whenpostgres-analyticsis fine.
Several installations of one service
When aservice: entry matches more than one installation, any ready one satisfies it, and the sync warns:
serviceInstallation: when it matters which one. You can name several installations of the same service; each must be ready and, if the release constrains the service, in range.
Renamed installations
Dependencies resolve by name. When a named installation is renamed or deleted, the old name stops resolving:- An installation that hasn’t installed yet waits with
installation dependency postgres-main not found; install postgres-main or remove it from dependencies. - An installation that is already running falls back to its release dependencies: its ranges apply to every installation of the service again, as if it named none.
dependencies doesn’t redeploy an installation; it re-checks a first install or an upgrade that is waiting.
Benefits
Service dependency constraints eliminate entire classes of production incidents: Without automated constraints, organizations typically either:- Require manual coordination to ensure features land in the same release cycle as their dependencies
- Risk production outages from version mismatches
- Spend significant time on manual remediation when things go wrong
- Automatic validation of cross-service compatibility
- Prevention of broken deployments before they happen
- Elimination of manual coordination between teams
- Safe, progressive rollout of breaking changes
Best practices
Declare constraints at feature merge time: Add dependency constraints to release metadata when merging features that require them, not retroactively. This ensures the constraint is present when the release is published. Use version ranges to express compatibility windows: SetminVersion to the first provider version with required functionality, and maxVersion to the last known compatible major version (e.g., 0.x.x or 1.x.x). This allows Ryvn to safely upgrade within compatible versions.