Some life sciences data has to stay inside a closed network. Hospital systems, defense and government research, and organizations with strict data residency rules run environments with no route to the public internet, so a cloud based platform is only of use to those teams if it runs there too.
Cloud native platforms lean on services the cloud vendor runs for them: object storage, managed databases, message queues, identity providers, container orchestration. None of those exist in an air gapped environment. Each one needs a local replacement that behaves the same way, or the on premises deployment ends up different from the cloud version and the team has two products to maintain.
Software that expects to pull updates, container images and dependencies from the internet has nowhere to pull them from. Everything has to be bundled, delivered offline and verified, then installed by a process that works without a connection.
In the cloud, compute can be spun up for a large analysis and released afterwards. Fixed hardware does not stretch like that, so workloads have to be scheduled against what is physically there.
Each part of the platform goes in a container with its own dependencies, which makes the deployment less dependent on the hardware underneath. Kubernetes takes over the scheduling and resilience the cloud used to provide. Where hardware is limited, we use a lighter orchestrator.
We swap each managed cloud service for a self hosted one, so cloud object storage becomes a local object store and a managed database becomes the same database running in the cluster. The swap sits behind an abstraction and the application code does not change.
Planning both deployments from the beginning makes it easier to keep the on premises version on the same core features as the cloud one.
The deployment runs without outbound network access.
Each one can cause a failure that is difficult to spot from outside the network, so finding and removing those dependencies is part of the deployment work.