Skip to main content

KubeVela's OAM Delivery Engine Runs Alibaba's Hybrid Cloud and ByteDance's Gaming PaaS: What It Buys Over a Simpler Git-Push Deploy API

8 min readDora NodaDora Noda
Share
On this page

KubeVela just shipped v1.11.0 on July 20, 2026 — ten days before this post — and it's still adding releases at a steady clip nearly six years after Alibaba open-sourced it in November 2020. The project has 7,868 GitHub stars, CNCF Incubating status since February 2023, and two adopters worth taking seriously: Alibaba runs it as the delivery core for its own hybrid-cloud application fleet, and ByteDance runs it — paired with Crossplane for infrastructure and Agones for game-server lifecycle — as the application-delivery layer under its gaming PaaS. Neither company is deploying toy workloads.

So here's the concrete question this post answers: on top of a fleet that's already declaratively managed — the same reconciliation loop Cluster API gives a self-hosted platform like bex — what does KubeVela's OAM abstraction actually add? The answer is two specific things, and only two: an application-level desired-state object (components, traits, and policies that describe what an app is, not just what machines exist), and a workflow engine (canary steps, suspend gates, multi-cluster promotion) that a bare reconciliation loop has no concept of. A Render-compatible git-push deploy API — request a deploy, get a URL — doesn't have either of those either. The rest of this post shows exactly what that gap looks like in YAML, where Alibaba and ByteDance actually needed it, and where the honest answer is that most git-push PaaS tenants shouldn't pay for it.

What a reconciliation loop reconciles — and what it doesn't

Cluster API's reconciliation loop, the one CAPH runs against Hetzner machines for a platform like bex, has one job: make the observed state of machines and clusters match a declared spec. A HetznerBareMetalMachine object says "this node should exist, running this OS image, joined to this cluster" — and the controller loops until reality matches that, replacing hardware that fails a health check without a human touching a runbook.

That loop knows nothing about what's running on the cluster. It has no concept of "this service," let alone "canary 20% of this service's traffic to the new version, wait for a health signal, then promote the rest." Machine-level reconciliation and application-level delivery are different problems, reconciled by different controllers, against different desired-state objects — and that's exactly the boundary OAM's Application custom resource sits on. Where Cluster API's spec describes a machine, an OAM Application describes a component (the workload — a container image, a Helm chart), decorated by traits (attached operational behavior — a scaler, a canary rollout, a sidecar), constrained by policies (an environment-binding rule, a firewall constraint, an override), and driven by a workflow (the ordered steps that actually ship a deployment: deploy, suspend for approval, canary, promote). That's four new abstraction layers a reconciliation loop for machines doesn't have — because it was never asked to have them.

Two adopters, two different reasons to need that layer

Alibaba and ByteDance didn't reach for OAM's application layer for the same reason, and pretending they did erases the more useful lesson.

Alibaba built KubeVela around its own hybrid-cloud delivery problem before open-sourcing it. The project's core design choices — GitOps-based delivery as the default flow, first-class Helm component support, multi-cluster and multi-cloud environments as the primary delivery target rather than an add-on — trace directly to Alibaba's internal practice of running application fleets that span multiple clusters and multiple cloud environments at once, not a single cluster with a single desired state. Alibaba still uses KubeVela as that delivery core today. For a platform team promoting one artifact through many independently-reconciled clusters, "which cluster is this component supposed to run in right now" is a question a single Cluster API fleet's reconciliation loop was never built to answer, because CAPI's spec is per-cluster by design — it doesn't know other clusters exist.

ByteDance needed the same application layer for a narrower, more specific reason: coordinating three different control planes for one workload. Its gaming PaaS runs Crossplane to provision multi-cloud, multi-region infrastructure (game-server hosts, network resources, dependency services), Agones to manage the stateful lifecycle of individual game server instances (fleet scaling, allocation, graceful shutdown), and KubeVela to sit above both as the delivery workflow that ties a release to a rollout across all of it. None of those three tools reconciles what the other two reconcile — Crossplane doesn't know about game-server allocation state, Agones doesn't provision cloud resources — and OAM's Application object is the layer that expresses "this release, this component, deployed via this workflow, across whichever clusters this policy names" as one coherent object instead of three uncoordinated ones.

The shared thread: both companies needed application-level orchestration because they were already running multiple independently-reconciled infrastructure layers or clusters, and needed one object above all of them that knows what a release is. That's a specific precondition — not "we run Kubernetes," but "we run enough separate reconciled surfaces that nothing already tracks the release as a single thing."

The YAML delta, concretely

Here's what that buys you in KubeVela, trimmed to the parts with no equivalent in a simpler deploy API:

yaml
apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: game-api
spec:
  components:
    - name: game-api
      type: webservice
      properties:
        image: registry.example.com/game-api:v2.3.0
      traits:
        - type: scaler
          properties: { replicas: 3 }
  policies:
    - name: multi-env
      type: env-binding
      properties:
        envs:
          - name: staging
            placement: { clusterSelector: { name: staging-cluster } }
          - name: prod
            placement: { clusterSelector: { name: prod-cluster } }
  workflow:
    steps:
      - name: deploy-staging
        type: deploy2env
        properties: { env: staging }
      - name: manual-approval
        type: suspend
      - name: canary-prod
        type: canary-deploy
        properties: { component: game-api, canaryReplicas: 1 }
      - name: promote-prod
        type: deploy2env
        properties: { env: prod }

Twenty-eight lines, and every section past components is doing something a reconciliation loop and a deploy API both lack: the policies block names two different clusters as first-class deploy targets for the same application object; the workflow block sequences an approval gate and a canary step as explicit, resumable steps rather than a script a CI job runs once and forgets. Compare that to the equivalent request against a Render-compatible deploy API — the model bex uses:

yaml
# bex.yml
service: game-api
image: registry.example.com/game-api:v2.3.0
port: 8080
text
POST /v1/services/game-api/deploys
{ "image": "registry.example.com/game-api:v2.3.0" }

Four lines and one API call. Push, get a URL, it's running. That's not a stripped-down version of the KubeVela example — it's a different model that doesn't represent multi-cluster placement or a staged rollout at all, because a single-cluster, single-environment deploy request has no field for "which cluster" or "wait for approval before the next 50%." The gap between the two isn't verbosity; it's that the deploy-API model has nowhere to put a canary step even if you wanted one, while OAM's workflow array exists specifically to hold a sequence of them.

Whether that's a gap in bex's roadmap or a bill worth not paying

That YAML delta is a real capability, not busywork — Alibaba and ByteDance didn't add four abstraction layers for aesthetic reasons. But "real capability" and "worth building" are different questions, and the honest answer depends entirely on which side of one threshold a tenant sits on.

Below the threshold — the common case for a git-push PaaS: a single service, deployed to one production environment (maybe a staging environment ahead of it), on a fleet a platform team already operates as one reconciled unit. For that tenant, "push, get a URL" is the complete workflow — there's no second cluster to place a canary on, no second team's approval to gate on, no infrastructure control plane that KubeVela needs to coordinate against because there's only one. Building an Application/component/trait/policy/workflow object model for that tenant adds four YAML sections that resolve to the same single deploy every time. That's not a missing feature; it's YAML with nothing to say.

Above the threshold — multiple clusters, multiple environments as explicit named promotion targets, multiple teams sharing a fleet: the value proposition flips, because at that point "which cluster does this go to, in what order, with what gate in between" stops being a question a single deploy request can even express, no matter how well-designed the request format is. That's Alibaba's precondition (multi-cluster/multi-cloud as the delivery target, not an edge case) and ByteDance's precondition (three control planes that need one coordinating object) — both scales built the abstraction because they'd already crossed the point where a single desired-state object per deploy stopped being sufficient.

For bex specifically, that means the workflow layer isn't a current gap — it's a complexity budget correctly not spent yet, because bex's tenants today are the below-threshold case: one service, one or two environments, one fleet. It's also not a permanently closed question. The day bex tenants are routinely promoting one release across multiple named clusters with a gate in between, an OAM-shaped Application object — not a bolted-on flag on the existing deploy endpoint — is the right shape to reach for, because it's solving the same problem KubeVela's workflow engine solves: representing a multi-cluster promotion as one object instead of a sequence of manual API calls a human has to sequence by hand.


Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, backed by Cluster API's declarative fleet management instead of a hand-managed server pool. Star the repo on GitHub or deploy your first app today.

Sources

Related articles

Run this on infrastructure you own

bex is the open-source, AI-native Render alternative — push a git repo and get a running HTTPS service on your own machines.

Get started with bex