Dev Experience Invariant
Fractal Cloud guarantees a single, binding rule for application developers:
One workload produces one common artifact set, regardless of which cloud the workload eventually runs on.
A developer who writes a service does not write Azure code, AWS code, or GCP code. They build their artifact once. The platform — fractals, live systems, and agents — handles every cloud-specific concern downstream.
The contract
For containerized workloads, the artifact is a single OCI container image. The image is published to whichever registries the target clouds need: Azure Container Registry, Amazon ECR, Google Artifact Registry, Aruba's container registry, or any combination. The image bytes are identical across registries.
For Spark jobs, the artifact is a single Python wheel, published as an OCI artifact (using oras push) to those same registries. The wheel bytes are identical across registries.
That is the entirety of the developer's per-workload output: one image, or one wheel, copied to N registries.
How the agents wrap
The cloud-specific work happens in the agents, not in the developer's code.
Container workloads
- On a Kubernetes-backed cloud (AKS, EKS, GKE, Aruba KaaS), the CaaS agent renders a
Deploymentand aService, then writes them with server-side apply. - On a serverless container platform (Azure Container Apps, AWS App Runner, Cloud Run), the appropriate agent translates the same blueprint into the platform-native object.
- The image reference is taken from the live-system component's
artifactUriparameter; the agent picks the registry that the target cloud can pull from.
Spark jobs
- On Databricks (Azure, AWS, or GCP), the Databricks agent downloads the wheel, uploads it to the workspace as a Library on a Unity Catalog Volume (or DBFS for legacy workspaces), and creates a job with a
python_wheel_taskspec. The task references the uploaded wheel by name and invokes the declaredentryPoint. - On Spark-on-Kubernetes, the agent emits a
SparkApplicationCR. An initContainer runsoras pullto fetch the wheel into a shared volume, and the driver and executor containerspip installit before launch. - In both cases the developer's wheel is bit-for-bit the same artifact.
Serverless functions (FaaS)
- A function's code is published as an OCI artefact — a container image or a source zip — to the same registries used for container images.
- The component references it with a single
sourceArtifactparameter (the OCI coordinate in the customer's registry). The agent pulls it and wraps it into the cloud-native primitive: AWS Lambda (image or zip-via-S3), Azure Function (Linux container orWEBSITE_RUN_FROM_PACKAGEblob), or Google Cloud Function (GCS source). The developer never stages code into a provider bucket. - See Create Serverless Function (FaaS) for the end-to-end how-to.
What the fractal blueprint expresses
The blueprint declares the artifact contract, not the cloud specifics:
| Parameter | Description |
|---|---|
artifactUri | Abstract registry coordinate of the artifact (resolved per-cloud at the live-system layer) |
artifactType | container or python_wheel |
entryPoint | For wheels: module:function invoked by the runtime |
entryPointArgs | Optional list of CLI-style arguments passed to the entry point |
The live-system layer — not the developer — maps the abstract coordinate to a concrete registry per target cloud. The agent — not the developer — wraps the artifact into the cloud-native primitive.
Why this matters
The invariant exists so that a workload written for one cloud runs unchanged on any other cloud the platform supports. Without it, every team eventually writes:
- A Dockerfile for local development.
- An AKS Helm chart.
- An EKS Kustomize overlay.
- A Databricks notebook for the analytics path.
- A Cloud Run service definition.
Each of those is a separate codebase tracked, reviewed, and updated by the application team. Each is a place where production drifts from local. Each is a vendor lock-in surface.
The invariant collapses all of that. A new cloud is onboarded by writing an agent — done once, by the platform team — and every existing workload runs on it without source changes.
Anti-pattern: the hand-written Databricks notebook
If a developer hand-writes a Databricks notebook, the workload no longer has a portable form. The notebook is bound to the Databricks runtime, the Databricks workspace path layout, the Databricks secret-scope mechanism, and the Databricks job-scheduling model.
Concretely:
- The notebook cannot be run locally without simulating Databricks utilities (
dbutils,%run, etc.). - The notebook cannot be lifted to a self-hosted Spark cluster on Kubernetes without rewriting the entry point.
- The notebook cannot be diff-reviewed in a normal pull request flow because of cell metadata noise.
The platform-aligned alternative is to build the same logic as a Python module published as a wheel. The wheel runs locally under pyspark, runs on Databricks via python_wheel_task, and runs on Spark-on-K8s via SparkApplication. The same code path, the same tests, the same artifact.
If you find yourself writing a notebook, you have lost portability. Stop and refactor into a wheel.
Summary
- One artifact per workload. Always.
- Container image for services, Python wheel for Spark jobs.
- Published to whichever registries the org's target clouds require.
- Agents handle the cloud-specific wrapping.
- The blueprint declares the artifact contract; the live system resolves it; the agent reconciles it.
This is the developer experience that Fractal Cloud commits to, in writing.