---
id: SOV10
pillar: sovereignty
title: SOV 10. How do you preserve the ability to move the workload elsewhere?
description: Reversibility is designed in or absent. It is less about avoiding managed services than about knowing what each one costs to leave, before you depend on it.
status: draft
services: [object-storage, kubernetes-engine, cloud-foundry, postgresql-flex]
tiers: [1, 2, 3]
sidebar:
  order: 19
  label: Open interfaces
source_url: "https://framework.stackit.cloud/architecture/pillars/sovereignty/sov-10-open-interfaces/"
source_file: "docs/architecture/pillars/sovereignty/sov-10-open-interfaces.mdx"
---

Reversibility is a sovereignty property in a specific sense: a dependency you cannot leave is a
dependency that decides your terms. That matters for regulatory requirements that ask for an exit
capability, and it matters for the ordinary commercial reason that an alternative you could
actually take is what makes a negotiation a negotiation.

The naive version of this question is to avoid managed services, which trades a large certain cost
for a small uncertain one and usually produces a worse system. The useful version is to know what
each dependency costs to leave, and to accept that cost deliberately where the service is worth
it.

## Best practices

- [`SOV 10.1`](/architecture/pillars/sovereignty/sov-10-open-interfaces/#sov-101-prefer-open-interfaces-where-the-alternative-is-equivalent) Prefer open interfaces where the alternative is equivalent
- [`SOV 10.2`](/architecture/pillars/sovereignty/sov-10-open-interfaces/#sov-102-keep-data-in-portable-formats-and-know-how-to-get-it-out) Keep data in portable formats and know how to get it out
- [`SOV 10.3`](/architecture/pillars/sovereignty/sov-10-open-interfaces/#sov-103-separate-what-is-portable-from-what-is-provider-specific) Separate what is portable from what is provider-specific
- [`SOV 10.4`](/architecture/pillars/sovereignty/sov-10-open-interfaces/#sov-104-price-the-exit-for-each-dependency-and-accept-it-explicitly) Price the exit for each dependency and accept it explicitly

---

## SOV 10.1 Prefer open interfaces where the alternative is equivalent

**Risk if not established:** Medium

An interface with several independent implementations is one you can leave without rewriting.
Where a standards-based option is equivalent in capability, taking it costs nothing and preserves
the option.

The qualifier matters. Where the proprietary option is genuinely better, taking the open one to
preserve portability is paying a permanent cost for a contingency, and that trade should be made
consciously rather than as a rule.

The interfaces that carry the most weight are the ones the whole workload sits on: the container
orchestrator, the object storage protocol, the database engine, the application runtime, and the
messaging protocol. A portable choice at those layers preserves far more than a portable choice at
the edges.

Distinguish the interface from the implementation. A managed service exposing a standard interface
is portable at the interface even though the operational surface differs, and that is usually the
practical middle: the provider operates it, and your code does not know which one.

**On STACKIT.** The platform is built on this pattern at nearly every layer, which is what makes
the practice available rather than aspirational.

<LinkChip href="https://docs.stackit.cloud/products/storage/object-storage/">Object Storage</LinkChip> is S3-compatible,
including <LinkChip href="https://docs.stackit.cloud/products/storage/object-storage/reference/lifecycle-configuration/">lifecycle
configuration</LinkChip>
and versioning through the same API, so the storage layer of an application is expressed in an
interface with many implementations.

<LinkChip href="https://docs.stackit.cloud/products/runtime/kubernetes-engine/">Kubernetes Engine</LinkChip> runs upstream
Kubernetes, and <LinkChip href="https://docs.stackit.cloud/products/runtime/cloud-foundry/">Cloud Foundry</LinkChip> is an
open platform, so the workload definition is portable at the level that matters most.

The managed data services run open-source engines, for example
<LinkChip href="https://docs.stackit.cloud/products/databases/postgresql-flex/">PostgreSQL</LinkChip> and the <LinkChip href="https://docs.stackit.cloud/products/databases/key-value-store/">key-value
store</LinkChip>, which means the wire
protocol and the query language your application depends on are not provider-specific.

The layer that is provider-specific is provisioning, which the <LinkChip href="https://docs.stackit.cloud/developer-tools/stackit-iac/stackit-terraform-provider/">Terraform
provider</LinkChip> and
the <LinkChip href="https://docs.stackit.cloud/developer-tools/stackit-api/">API</LinkChip> express. That is the correct
place for it to sit, since it is the layer [`SOV 10.3`](/architecture/pillars/sovereignty/sov-10-open-interfaces/#sov-103-separate-what-is-portable-from-what-is-provider-specific) asks you to separate anyway.

**Tradeoffs.** **Performance Efficiency** and **Operational Excellence.** A standard interface
sometimes lags a proprietary one in capability, and portability is worth less than a feature the
workload genuinely needs.

**Verify.** For each major interface your workload depends on, how many independent
implementations exist? Which of your dependencies has exactly one?

---

## SOV 10.2 Keep data in portable formats and know how to get it out

**Risk if not established:** Medium

Data is the part of a migration that dominates. Code can be rewritten on a schedule; a large data
set in a format only one system reads is what makes an exit a project rather than a decision.

Two properties are needed and they are separable. The **format** has to be readable by something
else, meaning a documented schema or an open format rather than an internal representation. The
**export path** has to exist and be usable at your actual data volume.

The second is where plans fail. An export that works for a gigabyte and takes weeks for the real
data set is not an export path, and nobody discovers that until they try it, which is why [`SOV 11`](/architecture/pillars/sovereignty/sov-11-exit-plan/)
asks for the test.

Include the parts that are not the primary store: object metadata, access policies, schema
definitions, configuration and the historical records you are obliged to retain. A migration that
moves the rows and leaves the retention history behind has not moved the obligation.

Know the shape of the constraint as well as the mechanism. Volume, time and cost are all real
limits, and egress at scale takes long enough that it belongs in a plan rather than in an
assumption.

**On STACKIT.** Because the managed engines are open-source, their native export mechanisms are
the export path, and those are widely understood tools rather than proprietary ones. Object
Storage's S3 compatibility means the standard ecosystem of transfer tooling applies to the object
layer.

What the platform does not remove is the physics. Moving a large data set takes the time it takes,
and that figure is a property of your data rather than of the platform, which makes measuring it
the only way to know it.

**Tradeoffs.** **Performance Efficiency.** A portable format is sometimes less efficient than a
proprietary one, which is a real cost paid continuously against a contingency.

**Verify.** For your largest data set, what is the export path and how long would exporting it
take? Has anybody measured that rather than estimated it?

---

## SOV 10.3 Separate what is portable from what is provider-specific

**Risk if not established:** Medium

Every workload has provider-specific parts and that is fine. What decides the cost of an exit is
whether those parts are identifiable or spread through the application.

Draw the boundary deliberately. Business logic should not know which provider it runs on.
Provider-specific concerns belong behind an interface, in a configuration layer, or in the
infrastructure definitions rather than in the code paths that implement the product.

The recurring leak is a provider SDK imported directly into business logic. It works, it is
convenient, and it means the provider dependency is now distributed across the codebase rather
than concentrated where it can be replaced.

Infrastructure definitions are the honest exception. They are provider-specific by nature and
rewriting them is a known, bounded cost, which is a much better position than a diffuse dependency
nobody can enumerate.

Resist over-abstraction. A layer designed to support a hypothetical second provider costs
complexity now for a benefit that usually never arrives, and it frequently reduces to the
intersection of both providers' capabilities. Concentrating the dependency is the goal rather than
hiding it.

**On STACKIT.** The natural boundary is that the workload interfaces are open and the provisioning
layer is not. Your application speaks Kubernetes, S3, PostgreSQL and HTTP; your
<LinkChip href="https://docs.stackit.cloud/developer-tools/stackit-iac/stackit-terraform-provider/">Terraform</LinkChip>
definitions and any use of the
<LinkChip href="https://docs.stackit.cloud/developer-tools/stackit-sdk/stackit-go-sdk/">SDKs</LinkChip> speak STACKIT.

That split is the one to preserve, and it happens by default unless a platform SDK is used inside
the application rather than at its edges.

**Tradeoffs.** **Operational Excellence.** An abstraction layer is code to maintain and can
obscure useful provider capabilities, which is why the goal is concentration rather than a full
abstraction.

**Verify.** How many files in your application import a provider-specific SDK? Could you list
every provider-specific component from memory?

---

## SOV 10.4 Price the exit for each dependency and accept it explicitly

**Risk if not established:** Medium

The point of this question is not to have no lock-in. It is to know what each dependency would
cost to leave, so that the decision to take it is a decision.

Estimate three things per significant dependency: the **engineering effort** to replace it, the
**data migration** cost and duration, and the **elapsed time** before the workload could run
elsewhere. Rough figures are enough, because the useful output is the ordering rather than the
number.

Then accept it. A managed service that saves substantial operational work and would cost three
months to leave is frequently a good trade, and recording that reasoning is what makes it
defensible later. The failure is not the dependency; it is discovering its cost during the
conversation where it matters.

Watch for the ones that are expensive and low-value: a proprietary component that saved a week of
work and now takes months to leave. Those are worth removing while the removal is cheap.

Revisit when circumstances change. A dependency taken when the workload was small can become the
most expensive thing in the estate as the data grows, and nothing signals that moment.

**On STACKIT.** Because most layers are open, the list of genuinely expensive exits is usually
short, and that is the point of making it: a short list is one an organization can actually act
on.

Where the answer for a given dependency is that leaving would be expensive, that is information
for [`SOV 11`](/architecture/pillars/sovereignty/sov-11-exit-plan/) and for the tier, rather than a reason to avoid the service.

**Tradeoffs.** None beyond the effort. Pricing an exit costs an afternoon per significant
dependency and turns a vague anxiety into a list.

**Verify.** For your three most significant provider dependencies, what would each cost to
replace? Where is that written down?

---

## Related

- [`SOV 11`](/architecture/pillars/sovereignty/sov-11-exit-plan/) Exit plan, which tests what this makes possible
- [`SOV 6`](/architecture/pillars/sovereignty/sov-06-jurisdictional-chain/) Jurisdictional chain, whose changes this decides the cost of responding to
- [`REL 5`](/architecture/pillars/reliability/rel-05-resilient-interactions/) Resilient interactions, the reliability view of the same dependencies
- [`COST 1.2`](/architecture/pillars/cost-optimization/cost-01-cost-model/#cost-12-include-operational-labour-not-only-resource-consumption) Managed versus self-operated, the same trade priced financially
- [`SOV 1`](/architecture/pillars/sovereignty/sov-01-sovereignty-tier/) Tier, which sets how strictly this binds
