Skip to main content
Service-oriented architectures rely on inter-service communication governed by API contracts. Coordinating these cross-service relationships is critical for safe deployments. Ryvn’s service dependency constraints drastically reduce the manual effort involved in feature rollouts and deprecated API removal by automatically enforcing cross-service compatibility.
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 the consumer 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.
Here are both for a web service that uses postgres:
The release says this version of 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

Suppose consumer 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:
The dependency is part of the release metadata when you publish 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 the consumer 0.9.0 release, it checks whether existing installations can safely upgrade. Consider an environment in this state:
Before upgrading 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 installed consumer 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. Add dependencies to the installation:
Installation dependencies have no version bounds; versions stay in the release file. Blueprints can declare them on their services too. For configuration on installations and blueprints, see Installation Dependencies. For the property reference, see dependencies on server, job, Helm chart, and Terraform installations.

Ordering the first install

When web-production and postgres-main are declared in the same sync, postgres-main installs first. web-production waits with a dependency issue such as:
It installs automatically once 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 the web 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-analytics to 17.0.0 proceeds.
  • Upgrading postgres-main to 17.0.0 is blocked:
  • web-production’s own deploys wait if postgres-main is out of range or not ready, even when postgres-analytics is fine.
Naming an installation only narrows a check the release already declares. An installation dependency never adds a version constraint, and never blocks its target from upgrading or uninstalling on its own.

Several installations of one service

When a service: entry matches more than one installation, any ready one satisfies it, and the sync warns:
Switch to 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.
A sync that renames an installation warns about every installation whose dependencies still use the old name. Update those dependencies to the new name to restore narrowing. Changing only 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
With Ryvn’s automated constraints, you get:
  • 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: Set minVersion 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.