How Flui works across providers
This chapter is the foundation. Every later chapter that talks about infrastructure — clusters, networks, firewalls, DNS, credentials — builds on the abstraction described here.
The problem
Two cloud providers can look very similar and behave very differently.
- What sits next to “a server” varies wildly. One provider offers managed DNS, firewalls, private networks, load balancers and snapshots, all through the same API. Another gives you a server and almost nothing else. Building a platform on top of either provider requires very different work.
- Billing models do not match. One provider bills by the hour and stops charging the moment you delete the resource. Another bills monthly under contract. Some vendors mix both inside the same catalogue.
- The same idea is named differently. A server can live in a location, a zone or a region depending on the provider. The words are not interchangeable: each one carries its own meaning about scope, redundancy and pricing.
- SSH keys, firewalls, private networks and DNS are each modelled differently again. Same idea, four different APIs, four different shapes.
Even one vendor can ship two compute products that look interchangeable but behave very differently. Only one of them may suit the elastic, autoscaling workloads Flui is built for.
A naive integration ends up with provider-specific branches scattered across the CLI, the API and the dashboard. The cost grows with every new provider, every new feature, every edge case, until adding a third provider is a project on its own.
What Flui does instead
Flui’s goal is concrete: get your applications online as quickly as possible, on the cloud provider you choose, and let you scale up without rewriting your platform as traffic, team or workloads grow.
The gap Flui closes is widest on providers that don’t ship a managed platform of their own — that is where Flui’s case is strongest. The same model also serves teams on providers that do ship one, when keeping applications portable across clouds matters more than tying everything to a single vendor’s stack.
To deliver that goal across providers that vary so much, Flui sits as a single abstraction layer between the rest of the system and the cloud provider, with two non-obvious properties:
- It is not the lowest common denominator. When a provider lacks a capability, Flui says so — and may simulate, fall back, or degrade gracefully — rather than pretending the capability does not exist.
- It is capability-aware. Each provider declares which of a fixed set of capabilities it supports; the rest of Flui adapts its behaviour accordingly, without provider-specific branches in user- facing code.
The result is a two-layer architecture. Each provider has its own isolated module, which is the only place that knows how that specific cloud behaves. On top sits Flui’s cross-cutting core — the CLI, the dashboard, the orchestration engine, the application model, the operations layer — which is the same regardless of which provider is underneath. The core talks to “a provider”, never to “this specific cloud”; provider differences are absorbed by the modules below, not propagated upwards.
Portability and lock-in
The abstraction has an explicit position on vendor lock-in. The portable layer covers two things:
- The
flui.yamlmanifest describes an application and its app-level resources — build, deploy, scaling profile, endpoints, domains. The same manifest, unchanged, describes the same app on any integrated provider. - The operating model — clusters, environments, deployments, observability — driven by the CLI, dashboard and API. The surfaces and commands are the same regardless of which provider is underneath.
A third layer of portability comes from the runtime itself. Flui runs workloads on K3s — upstream Kubernetes — which is installable on practically any Linux machine: any cloud, any bare metal, any edge box. At runtime, the applications you deploy through Flui are standard Kubernetes workloads; in principle they can run wherever K3s can run.
What is provider-specific stays provider-specific on purpose — the underlying machines, the regions, the catalogue of instance types. A later section in this chapter unpacks where that line falls.
Moving from one provider to another is therefore a matter of re-provisioning infrastructure under a different credential, then redeploying the same applications from the same manifests on top.
Portability is not just a future escape hatch. Because the operating model and the manifest are the same across providers, Flui supports running parallel workloads on different providers at the same time: the same Flui control plane can drive clusters on multiple integrated clouds in parallel. Flui also encourages cross-provider backups: data lives on one provider, backups land on another, so a provider- level outage or account incident does not take everything down at once.
Modes of integration
Flui’s integration with the underlying infrastructure comes in three modes, each with its own automation boundary:
- Flui Full. Full integration with a cloud provider. Provisioning, firewall, DNS, private network and storage (block and object) are all exposed by the provider and automated end-to-end. The user never has to step into the provider’s console for routine operations.
- Flui Partial. The provider exposes the baseline — Flui can provision servers, and the provider bills by the hour — but does not expose every capability through its API. Flui automates what it can; the rest, typically firewall rules or DNS records, the user manages manually in the provider’s console. The platform on top is the same as in Full mode; only some operations stop short of end-to-end automation.
- Flui BYOS (bring-your-own-server, planned). No cloud provider in the picture. You point Flui at a Linux machine you already own, and Flui installs on top. There is no provisioning to automate — the machine is already provisioned by you — but everything Flui ships on top (clusters, ingress, TLS, observability, …) is the same as in the Full or Partial modes.
The mode is determined by what the provider exposes, not by what the user picks. A provider that supports every capability Flui needs ends up in Full mode; one that supports only some of them ends up in Partial mode. BYOS is a separate path: it skips the provider layer entirely.
Behind the modes, Flui tracks a finer set of capability dimensions each provider can declare — server lifecycle, hourly billing, SSH key registry, firewall, DNS, private network, block storage, object storage, power management. For each dimension Flui cannot automate, the manual fallback is written down. The integrator does not have to guess what happens when their provider cannot do firewalls; it is documented.
Flui leverages the primitives each provider exposes, and abstracts the complexity around them. Where a capability is available through the provider’s API — managed firewalls, DNS zones, private networks, volumes — Flui drives it directly and surfaces a uniform experience on top. Where it isn’t, the platform on top still looks the same, and only the missing piece becomes a manual step. The provider’s strengths come through; the user always sees the same Flui.
What the abstraction hides — and what it deliberately does not
The abstraction works in two directions. Most of the time you talk to Flui in Flui terms — anything the user normally has to think about is expressed that way.
| Flui concept | What it represents |
|---|---|
cluster | A set of servers with a private network, a firewall, and cluster-scoped resources, all tagged as managed by Flui. |
node | A provisioned VM or bare-metal server inside a cluster. |
vnet + subnet | A private network and one or more subnets the cluster’s nodes attach to. |
firewall | A set of inbound/outbound rules attached to one or more servers. |
dns-zone | A managed DNS zone, when the provider exposes a DNS API. |
endpoint | A FQDN with TLS, attached to a workload, backed by an A-record and a certificate. |
manifest (flui.yaml) | Independent of any provider — see the manifest chapter. |
build / release / operation | Tracked centrally by Flui. Build execution is currently delegated to an external system; on-prem build execution is on the roadmap. |
A few things are deliberately not hidden. They stay provider-specific on purpose, because pretending otherwise would mislead the user:
- Server-type identifiers. Each provider has its own catalogue of instance shapes. Flui keeps a cache with pricing and availability per region, but does not pretend two different providers’ types are interchangeable.
- Region and zone codes. The user picks one; Flui validates it against the provider.
- Provider-side IP ranges. When a provider documents constraints on CIDRs or routes, those constraints win.
- External-side configuration. When something Flui needs touches a system outside the provider’s API — for example, delegating a domain registered elsewhere by setting NS records at the registrar — the user configures it manually on that external side. Flui manages what it can reach.
Why this is the design move that matters
A few non-obvious payoffs:
- Adding a provider does not destabilise the rest. A new provider integration is built as its own self-contained piece: it implements the abstraction and declares which capabilities the provider supports. The CLI, the dashboard and the orchestration engine stay untouched. The work needed is real, but it stops at the new integration’s own boundary.
- Dropping a provider is also self-contained. Every operation that touches a provider goes through a single point inside Flui. Removing a provider means removing that one integration — not chasing changes across the rest of the platform.
- Capability-driven UX without conditionals. Because the dashboard and the CLI consult the provider’s own capability declaration instead of hardcoding behaviour, a provider that gains DNS support next week gets DNS controls in the UI as soon as its capability flag flips — no client release required.
How this chapter is referenced elsewhere
- Cluster as a concept and Creating a cluster describe the cluster lifecycle in Flui terms; the provider work happens behind the abstraction described here.
- VNet and subnets, Firewalls and DNS integration each show the abstraction at work in one capability area.
- The control cluster — even the control cluster is just a cluster, and creating it goes through the same provider abstraction as any workload cluster.