KliqueContent HubReference architecturesDownload PDF
Klique AI · Reference architecture

Cloud autoscaler reference architecture

This reference architecture covers the following scenario: the Klique control plane runs on-prem, in the customer's data centre, and GPU work can burst to a cloud region when on-prem capacity is full. It shows how the components fit together, where each workload runs, and how model calls are routed and metered.

Control plane
On-prem, in the customer's data centre
GPU capacity
On-prem pools first, then a cloud region on demand
Model calls
One LLM gateway, on-prem, for self-hosted and public models
Written for
IT architects and sales engineers

How to read the diagram: numbered badges follow a compute provisioning task, lettered badges follow a model call.

USERSBuildersConsumersApps, pipelines& agentsCorporate data centre · on-premKlique control planeUI · API · MCPPolicies &profilesAutoscalerinstanceRecords, logs& usage ledgerVaults& SSOScheduler& compute resourcesOn-prem GPU poolsKubernetesworker daemonsSlurm partitionworker daemonsBare metalworker daemonsLLM gatewayone endpoint, meteredObject storagedatasets · outputsRegistryimages · modelsWANVPNCloud · AWS · Azure · GCP · neocloudRegionVPC / VNetAutoscalerVM autoscaler or the cluster's ownAuto-scaling GPU nodes · VMs or KubernetesGPU node+ worker daemonGPU node+ worker daemonAddedon demandInternal routescloud endpointsImagemirrorObject storagesame regionInternet · public model APIsAnthropicOpenAIAzure OpenAIGeminipulls its config · polls compute resources · HTTPS outcalls the cloud API →123456ABCD
StepDetailLocationConnection
A compute provisioning task, from submission to scale-down
1SubmitA user, app, pipeline, schedule or agent sends work to a compute resource, from the UI, a session, the SDK or MCP.Control planeCaller → control plane, HTTPS
2Run on-premThe scheduler checks the team's policy and admits the task to the first pool in IT's order, on-prem. A worker daemon there pulls it and starts the container.On-prem GPU poolWorker daemon → control plane, outbound
3OverflowOnce on-prem's declared capacity is used up, the next task is admitted to the cloud pool instead.Control planeNone: a scheduling decision
4Scale upA GPU node is added: by Klique's VM autoscaler, or on managed Kubernetes (AWS, Azure, Google Cloud or a neocloud) by the cluster's own node autoscaler (section 03). The task starts there with its image and code.Cloud VPCAutoscaler → cloud API; worker daemon → control plane, outbound HTTPS
5Run near the dataThe task reads its data and writes checkpoints and models to storage in the same region.Cloud regionStays in the region
6Report & scale downLogs, metrics, status and output pointers stream home. Once the idle timeout passes, the node is removed.Cloud → control planeOutbound HTTPS, small payloads
A model call
AOne endpointApps, agents and IDEs call the LLM gateway with their own identity. They ask for an alias such as chat, not a vendor model.On-prem LLM gatewayCaller → LLM gateway, HTTPS
BSelf-hosted, on-premRoutine and sensitive traffic goes to self-hosted models on on-prem GPUs.On-prem GPU poolNever leaves the building
CSelf-hosted, cloudExtra capacity for the same model, served in the cloud region on a static route, behind that site's internal routes.Cloud regionLLM gateway → the cloud site's internal routes, over the WAN
DPublic APIUsed only when a routing rule allows it. The provider key stays in the gateway.Model providerLLM gateway → internet

Every model call, B, C or D, is metered on the same ledger as GPU-hours: by user, project, model and the rule that routed it.

Business value

01

Where compute runs

For any sovereignty review, the first question is where compute runs. Every compute provisioning task works the same way: scheduling a task, launching an attended or unattended session, launching an agentic session, or deploying a model endpoint. In this scenario the container can start in only two places: an on-prem GPU node, or a GPU VM or Kubernetes node in the customer's own cloud account. Policy decides which, never the workload itself: a team can only send work to the compute resources it has been granted, and each of those is served in one place. The control plane never runs the workload. A small worker daemon at each site pulls the task and starts the container there.

FOR EXAMPLEScheduled taskunattendedAttended sessionVS Code · Jupyter · SSHAgentic sessionClaude CodeModel endpointvLLM deploymentUsersbrowser or local IDECorporate data centre · on-premKlique control planeApps worker daemonapp controllers, no dataRecords & logsvaults · policiesCompute resourceon-premCompute resourcecloudholds compute resources, records and secrets · starts no workloads itselfOn-prem Kubernetes · GPU poolGPU NODECONTAINERS IT STARTSTaskone or more GPUsVS Codea GPU fractionvLLMserves /v1Claude CodeCPU is enoughKlique worker daemonserves the on-premcompute resourcestartspulls workInternal routeson-prem sessions & endpointsObject storagedata · outputsLLM gatewayto self-hosted vLLM, or a publicAPI only if a rule allowsmodel callsfor a cloud session: straight to the cloud site's internal routesWANCloud · customer's own accountRegion · VPCAutoscalerKlique VM autoscaler, orthe cluster's autoscalerVM autoscaler polls the cloud compute resourceadds a GPU VM or nodea cluster autoscaler reactsto Pending pods insteadGPU VM or Kubernetes node · on demandCONTAINERS IT STARTSTaskcontainer or podVS CodesessionvLLMextra capacityClaude CodesessionKlique worker daemonserves the cloudcompute resourcepulls work · HTTPS outInternal routescloud sessions & endpointsObject storagesame regionImage mirrorfaster cold starts
Where a workload runs is set by policy, not by the workload. Whatever is provisioned, from any app in the catalogue, policy decides which compute resources a team may use. Each compute resource is served in one place: the customer's own GPU nodes, or GPU VMs or Kubernetes nodes created on demand in the customer's cloud account. Either way, users connect at the site where the workload runs, not through the control plane.

Policy decides the location

A task, session or endpoint is the same on-prem or in the cloud. Policy decides which compute resources a team may use. Each one is served by worker daemons in one place, and only those worker daemons can start a container.

The control plane orchestrates, the sites compute

It keeps the compute resources, records, policies and secrets. For apps like VS Code or vLLM, a small controller process runs beside it to manage the instance. That controller holds no data and does no compute.

Access goes to where it runs

Sessions and endpoints are reached through the internal routes at their own site. An on-prem session never touches the cloud. An agentic session's model calls go through the LLM gateway, which keeps prompts on self-hosted models unless a rule allows a public API.

Compute provisioning taskSpins up asSent to an on-prem compute resourceSent to a cloud compute resourceHow users reach itLeaves the site
Scheduled task
unattended: training, batch, pipelines
One container for the taskA pod on an on-prem Kubernetes node, a Docker container on a bare-metal host, or a Slurm jobA container on a GPU VM, or a pod on a GPU node in the customer's managed Kubernetes cluster, added on demandNot reached directly: progress shows in the UILogs, metrics, pointers to outputs
Attended session
VS Code · Jupyter · SSH · desktop
A controller on the apps worker daemon, plus the session container on a GPU nodeOn-prem node, often a fraction of a GPUCloud VMBrowser or local IDE → that site's internal routes → the containerSession status. Files and keystrokes stay at the site.
Agentic session
Claude Code and other coding agents
A controller, plus the agent's container. CPU is often enough.On-prem nodeCloud VMBrowser terminal through that site's internal routesModel calls go to the LLM gateway: a self-hosted model, or a public API only if allowed
Model endpoint
vLLM, SGLang, NIM deployments
A controller, plus the model-server container. Weights are pulled onto that node.On-prem GPU nodeCloud GPU VM, for extra capacityAn OpenAI-style URL on a static route at that site, usually listed behind the LLM gatewayToken usage. Prompts stay where the model and its callers are.

These rows are examples. Every workload in the app catalogue is provisioned the same way.

Sovereignty is enforced by the compute resource: if a team's work must never run in the cloud, don't give that team a cloud compute resource. Policies decide which compute resources each group can even see. A compute resource with no cloud pool behind it can only start containers on-prem.
02

The building blocks: one control plane, many pools

In this scenario the control plane lives in the customer's data centre. On-prem GPUs are grouped into resource pools: Kubernetes, bare metal or a Slurm partition. The cloud region is simply another pool, with an autoscaler in front of it. Every pool is served the same way. A small Klique worker daemon on each node polls the control plane for work, runs it and reports back.

A cloud account doesn't “connect to” Klique the way a cluster joins a network. It holds nodes that run a worker daemon, and each worker daemon asks the control plane for work. Adding a region, a second cloud or a neocloud is the same move each time: install the worker daemon, name the pool, link it to a profile. The network only has to work in one direction: the cloud side must be able to reach the control plane.
03

Autoscaler architecture

Klique bursts into a cloud account through VM autoscaling or managed Kubernetes. With VM autoscaling, a Klique autoscaler instance creates GPU VMs directly. With managed Kubernetes (EKS on AWS, AKS on Azure, GKE on Google Cloud, or a neocloud's managed Kubernetes), the Klique worker daemon runs inside the customer's cluster and the cluster's own node autoscaler adds GPU nodes. Both serve the same cloud compute resource, so users see no difference.

VM autoscaling

VM autoscaling has three moving parts. The autoscaler instance is defined in the control plane. An apps worker daemon runs it. The GPU VMs it creates are the only components that take work from the cloud compute resource, and they are removed again when idle.

IT adminsets it up onceUsers & agentstasks, sessions, appsCorporate data centre · on-premKlique control planeAutoscaler instancedefined & launched hereApps queueinternal, for appslaunch = placed hereITS CONFIGURATION · STORED IN THE CONTROL PLANEpollscloud compute resourceinstance type GPU instance · a set maximumcapacity spot, fall back to on-demandimage · init a prepared AMI, worker daemon in Docker modeidle timeout 15 min by defaultcredentials IAM role (or keys from a vault)Compute resourcecloudsend work to a compute resourceAlternative · run it on-premthe platform's own apps worker daemon runs the autoscaler here,with cloud keys read from a vaultWANCloud · customer's own accountRegion · VPCAlways-on CPU · IAM roleApps worker daemonlistens on the apps queueAutoscalerruns here, always onCloud APIcompute APIrun · terminateGPU VMs · created on demandGPU VMpulls workGPU VMpulls workNext VMonly if work waitseach VM's worker daemon pulls a task and starts its containeridle past the timeout → the autoscaler terminates the VMlaunchespulls the instancepolls for waiting work · registers as listenerVMs pull workHTTPS out12345678
StepDetailLocationTiming
1DefineAn admin creates an autoscaler instance: the compute resource to poll and its instance type, maximum instances, spot or on-demand, image, idle timeout and credentials.Control planeOnce
2LaunchLaunching it places it on the internal apps queue. At that point it is a record and a request.Control planeOnce
3StartAn apps worker daemon pulls it and runs the autoscaler as a small container. With the worker daemon on a VPC instance with an IAM role, no cloud keys are stored.Always-on CPU instance in the VPC, or on-premAlways running
4PollThe autoscaler checks the cloud compute resource about once a minute and registers as its listener, so work can be admitted to a pool with no VMs yet.Autoscaler → control planeAbout every minute
5Send workUsers send tasks, sessions or apps to the cloud compute resource, or on-prem overflow sends them there.Control planeOn demand
6Launch a VMWork is waiting and no VM is free, so the autoscaler calls the cloud API. It tries spot first if configured, then falls back to on-demand.Autoscaler → cloud APIWithin about a minute
7BootThe VM starts from a prepared image, and its start-up script launches a Klique worker daemon that serves the cloud compute resource.GPU VMA few minutes, image pull included
8Run & retireThe worker daemon pulls the work over outbound HTTPS and starts the container. A VM idle past the timeout is terminated by the autoscaler.GPU VM → control planeUntil idle, 15 min by default
Where the autoscaler runsOn-prem, on the platform's apps worker daemonIn the VPC, on an apps worker daemon with an IAM role
Cloud credentialsAccess keys, read from a vault at startNone stored. The instance's IAM role grants run, describe and terminate instances, tags and spot requests.
Network pathOutbound from the data centre to the cloud APIAPI calls stay inside the cloud provider. Only outbound HTTPS to the control plane crosses the WAN.
Extra always-on costNone: it uses the control plane's apps worker daemonOne small CPU instance, running all the time
Also runs thereThe apps worker daemon runs the controller for every app launched through it, not only the autoscaler. Choose its location on purpose. Controllers hold no data, but a security review will still want to know where they are.

Managed Kubernetes

When the customer already runs Kubernetes in the cloud, Klique uses it as the cloud pool. The Klique worker daemon runs as one deployment in the cluster and turns each task into a pod. The cluster's own node autoscaler (Karpenter or Cluster Autoscaler on EKS, the AKS cluster autoscaler, node auto-provisioning on GKE, or a neocloud provider's equivalent) adds GPU nodes for pods that can't be placed. No autoscaler instance is involved, and Klique holds no cloud credentials for scaling.

Users & agentstasks, sessions, appsCorporate data centre · on-premKlique control planePolicies &profilesRecords& logsVaults& SSONo autoscaler instance on this pathScaling is done by the cluster's own node autoscaler.Klique holds no cloud credentials for scaling.The Klique worker daemon runs as one deployment in the cluster.Compute resourcecloudsend work to a compute resourceWANCloud · customer's own accountRegion · VPCManaged Kubernetes · AWS · Azure · GCP · neocloudSYSTEM NODES · CPU · ALWAYS ONKlique worker daemonHelm deploymentInternal routescluster endpointsNode autoscalerKarpenter · CA · NAPcluster's own IAMGPU node pool · autoscaledGPU noderunning podsGPU noderunning podsNew nodefor a Pending podeach task runs as a pod with its GPU requestan empty node is removed after the consolidation delaypulls workHTTPSoutcreates a pod per tasksees Pending pods, adds a nodelogs · metrics123456
StepDetailLocationTiming
1Send workUsers send tasks, sessions or apps to the cloud compute resource, or on-prem overflow sends them there.Control planeOn demand
2PullThe Klique worker daemon in the cluster pulls the task over outbound HTTPS.Cluster, system nodesSeconds
3Create a podIt creates a pod with the GPU request from the compute resource's pod template. With no free GPU node, the pod waits as Pending.ClusterSeconds
4Add a nodeThe cluster's node autoscaler sees the Pending pod and adds a GPU node from the node pool, using the cluster's own IAM.GPU node poolA minute or two, plus the image pull
5Run & reportThe pod runs. Logs, metrics, status and output pointers stream home.GPU node → control planeUntil done
6Scale downWhen a node has no pods left, the cluster removes it after its consolidation delay.GPU node poolMinutes after idle
Fractional GPUs on managed Kubernetes: when every fractional slot on the running nodes is taken, the fractional-GPU admission check can reject a new pod instead of leaving it Pending. The node autoscaler then never sees the demand. Keep a small warm GPU node pool for fractional work, or run fractional work on-prem.

Choosing between them

Both variants serve the same cloud compute resource, so users see no difference. The choice is about what the customer already runs and who should hold the scaling permissions.

VM autoscalingManaged Kubernetes
Klique in the cloudAn autoscaler instance run by an apps worker daemon (on-prem with keys from a vault, or in the VPC with an IAM role), plus a worker daemon on every VMOne Klique worker daemon deployment on the cluster's system nodes, installed with Helm
ScalesGPU VMsGPU nodes in a node pool. Each task runs as a pod
TriggerWork waiting on the cloud compute resource, polled about once a minuteA Pending pod that no GPU node can fit
Cloud credentialsRun, describe and terminate instances; tag them; request spotNone held by Klique. The cluster's autoscaler scales with its own IAM
RemovesA VM idle past the timeout (15 minutes by default)An empty node, after the cluster's consolidation delay
PackingTypically one task per VMSeveral pods per node. Fractional GPUs possible
Serving endpointsInternal routes in the VPCInternal routes inside the cluster
CloudsAWS, GCP, OCI, Azure, neocloudsEKS, AKS, GKE and neocloud managed Kubernetes with a node autoscaler.
Best forThe simplest burst into a cloud account, with no cluster to runTeams already running Kubernetes in the cloud, dense packing
04

Many ways to provision, one compute resource

Compute is provisioned in many ways: from the app catalogue, in an attended session, from a script through the SDK or CLI, by a pipeline or schedule, or by an agent over MCP. Each one ends at the same place, a compute resource. It's the one choice made at provisioning time, and it carries no information about where the work will run. The GPU as a Service Reference Architecture covers each way to provision in more detail.

Launch an app from the catalogueOpen an interactive sessionClone a run, enqueue ittask.execute_remotely()clearml-task --queuePipelines · HPO · schedulesAn agent, over MCPCompute resourcethe only choice a user makescarries no locationResource policymay this team use it?how much do they hold?Profileallocation size:one whole GPU1st2ndOn-prem GPUspool · always thereCloud GPUspool · autoscaledused when the 1st is full
Placement is decided in one place, the profile's ordered pool links. It isn't decided by the user or by the way they came in. Re-order the links (cloud first, or a new region added) and every provisioning method follows, with no change to anyone's code, app or habits.

Launch an app

From the UI, for consumers and builders: pick an approved app (vLLM, SGLang or NVIDIA NIM for serving, JupyterLab or VS Code for development, Claude Code for agentic work) and choose a compute resource from a dropdown. The form never mentions a cluster, a node or a container.

Interactive sessions

Interactive, for builders: VS Code, Jupyter, SSH or a remote desktop, opened on platform GPUs rather than a laptop. A fraction of a GPU is often enough, and the session stays on it until the user closes it.

Clone & enqueue

Non-interactive, for builders: take any past run, change a parameter in the UI and send it to a compute resource. It's the same code with a different config. It runs unattended and reports back as it goes.

From an existing script

From the SDK: two lines to track a script, one more to hand it to the pool. The run stops locally and resumes on the GPU the compute resource provides.

from clearml import Task
task = Task.init(project_name="fraud-models", task_name="train")
task.execute_remotely(queue_name="compute resource")  # continues on the pool

Any script, no code change

From the CLI: wrap an existing repo or script and send it to a compute resource straight from the terminal or a CI pipeline.

clearml-task --project fraud-models --name nightly \
  --repo git@git.corp:ml/fraud.git --script train.py \
  --queue "compute resource"

Pipelines, HPO & schedules

Automation: each pipeline step, each hyperparameter trial and each scheduled or triggered run names its own compute resource. Prep on CPU, train on several GPUs, evaluate on a slice.

@PipelineDecorator.component(execution_queue="compute resource")
def train(dataset_id): ...

An agent, over MCP

Agentic: the platform is also a tool an agent can call. From Claude Code, a desktop assistant or a team's own agent, it can launch an app, enqueue a run, or read back a run's results. It works under the same identity, policy and attribution as the person who owns it. The agent never gets its own route to the hardware.

05

A cloud burst, step by step

Follow one training task. The on-prem GPUs are all busy, so the task overflows to the cloud region. The timeline shows each component's part and its typical duration.

≈ A MINUTEMINUTES · BOOT + IMAGE PULLTHE WORK · HOURSIDLE WINDOWControl planeAutoscalerCloud GPU nodeCloud storageTask waitsfor computeOn-prem full:admit to cloudSees demandon cloud poolNode boots,worker daemon joinsPulls task,image, codeReads datain regionRuns; logsstream homeWritescheckpointsIdle: noderemovedmetrics, consoleTypical order of events. Timings depend on node type, image size and the idle window IT sets.
The minutes are spent on boot and image pull, not on the platform. A GPU node can be ready in a minute or two. The first pull of a large serving image onto a fresh node can take about ten more. Pre-baked images, an in-region registry mirror, a persistent cache for model weights, or a small warm minimum all shorten it.

Scheduler

Behind every compute resource sits a small scheduler that runs about once a second. It works in three passes, and the order drives hybrid placement:

  1. Fill every team's reservation first. Try each profile's first pool, then its second, then the rest.
  2. Make room if a guarantee is being missed. If a team under its reservation is waiting and the pools are full, work from teams running over theirs is stopped and put back at the front of its queue.
  3. Then hand out the spare, up to each team's limit, again first pool before second.

“Full” means the pool's declared capacity, the number IT enters, is used up. When the scheduler picks a pool, it moves the task into a hidden queue that only that pool's worker daemons listen on. A cloud pool with no nodes yet still counts, because its autoscaler registers as the listener on that queue. This lets a pool scale from zero: the work is admitted first, and the node that runs it arrives next.

The same scheduler places work across Kubernetes, Slurm, bare-metal and cloud pools, covered in the Meta-Scheduler Reference Architecture.

TEAMSTeam Aunder reservationTeam Bover reservationComputeresourceKlique control planeResource policyreservation · limitProfilesize · ordered pool linksSchedulerruns about once a second123Fill every reservationfirst pool in the order, then the nextPreempt if a guarantee is missedstops over-reservation work, re-queues it firstHand out spare capacityup to each team's limit, same pool order1st2ndOn-prem poolPool queuehiddenWorker daemonson every nodepullGPUsowned capacityfull = declared capacity used upCloud pool · autoscaledPool queuehiddenAutoscalerregistered listenerpollsGPU VMsadded on demandzero VMs still counts as a pool: work is admitted first
The scheduler decides, the pools execute. Policy and profile feed one scheduler in the control plane. Each pool has its own hidden queue, served only by that pool's worker daemons, or in the cloud by the autoscaler that registers as its listener.
06

When it runs in the cloud, where does the work live?

Every security and data team asks this question. The control plane holds the record of the work, not the work itself. Heavy bytes (data, checkpoints, weights) stay beside the GPUs that use them. The data that comes home is small: parameters, logs, metrics, lineage, and pointers to where the outputs were written.

STAYS IN THE CLOUD REGION · HEAVYDataset copy, read and cached on the nodeContainer image, from an in-region mirrorCode checkout & model-weight cacheCheckpoints & models, when the output destination points hereA serving endpoint, if one is deployedScratch disk, gone at scale-downGB → TB · billed as egress only when movedWANCOMES HOME, ON-PREM · LIGHTThe task record: owner, repo + commit+ uncommitted diff, parameters, packagesConsole output, liveMetrics, plots, GPU utilisationPointers to outputs (the URI, not the bytes)Lineage: which data, which codeGPU-hours, for chargebackKB → MB · the audit trail, on-premreported homesecrets, at start
The dividing line is size and sensitivity, and one setting decides it for outputs. Everything needed to audit and reproduce the run comes home. Heavy bytes stay where the GPU is, if the task's output destination points at an in-region bucket. By default, outputs are uploaded to the control plane's file server, which is back across the WAN. Secrets travel the other way, once, at start-up.
AssetLocation during a cloud runCrosses back?
Task recordCreated on the control plane when the task is defined. It holds the repo, commit and uncommitted diff, parameters, packages, and who ran it.Lives on-prem
CodeCloned onto the node from the git server at start, and any uncommitted changes recorded on the task are applied. Or it's already baked into the container image. The node needs a route and credentials to the git server.No, stays in the region
EnvironmentRebuilt on the node from the recorded packages, or taken from the image, then cached for the next task on that node.No, stays in the region
Container imagePulled from a registry. Point cloud pools at an in-region mirror to cut cold starts and egress.No, stays in the region
Input dataA versioned dataset: metadata on the control plane, files in storage. It's fetched and cached on the node. For heavy data, store the dataset in an in-region bucket, or tell cloud workers to read the registered location from a local mirror.No, stays in the region
SecretsHeld in vaults on the control plane and injected into the task at start. They're never baked into images or code.No, flows out only
OutputsCheckpoints, artifacts and models go to the task's output destination. The default is the control plane's file server, back across the WAN. Set it per project or per pool to an in-region bucket to keep bytes in the cloud, or to on-prem storage for anything that must come home. The control plane records where they went.Depends on the output destination
Model weightsFor serving, downloaded at start from the model registry or Hugging Face. Put the cache on a persistent volume, or every cold node downloads them again.No, stays in the region
Logs & metricsStreamed to the control plane while the task runs, so a cloud task can be followed exactly like an on-prem one. Anything a task prints comes home too, so a task should never print secrets or raw records.Yes, streamed home
A model endpointRuns on the cloud node, on a static route behind that site's internal routes. The token traffic it serves is metered centrally (section 07).Usage records only
Scratch diskLocal to the node. Anything not written to an output destination is lost when the node is removed.No, removed at scale-down
For regulated data: the same mechanics run in reverse. Link a sensitive project's profile only to in-country or on-prem pools and keep its output destination on-prem. Its work then never lands in a cloud region, whichever way a user submits it.
07

Tokens: one gateway for every model

GPUs are one way to consume AI. Tokens are the other. Every model call, to a self-hosted model or to a public API, goes through one endpoint, the LLM gateway. The gateway checks who is calling, whether they're allowed, and whether their team has budget left. It then chooses a model from rules IT has set, and records the cost against the user and project. In this scenario the gateway runs on-prem, so every call enters through the customer's data centre, including calls to extra model capacity in the cloud region or to a public API.

App · agent · IDEasks for model “chat”with their own identityLLM gateway · one endpointhttps://ai.corp.example/llm/v1runs on-prem, beside the control planeWho is it?user or serviceaccountAllowed?access by group+ model accessBudget left?project & userquotas, rate limitsWhich model?alias → rules,highest match winsprovider API keys are held here and never handed to usersa user's key only says who is calling; access is granted per user,group and project, so revoking a person revokes all their keysSelf-hosted · on-prem GPUsvLLM, SGLang, NIM on owned poolsprivate by default · internal chargeback rateSelf-hosted · cloud GPUsserved in the region, behind a static routeextra capacity for the same modelPublic model APIAnthropic · OpenAI · Azure · Gemini · …when a rule sends it thereControl plane ledger· usage pushed regularly → user · project · model · rule that routed it · tokens · cost
The same four checks and the same ledger apply wherever the model runs. Rules can match the message text (with a regular expression), whether the request has tools or images, and the prompt size, as well as the project, the User-Agent and the model name. Fields the client sets itself, such as the entitlement tier header, should never drive a cost or compliance decision. Guardrails apply per AI resource or from the global policy, not ahead of routing. Users call an alias such as chat, not a vendor model. IT can move that alias from a public API to a model self-hosted on-prem, or to cloud capacity, with no change on the client side.

Where a token request goes, case by case

The model runs…Path of the requestMeteredGood for
On-prem GPUsClient → gateway → a self-hosted model server on owned pools. The request stays in the building.On-prem, at the internal rateRoutine and sensitive traffic, the default
Cloud GPUsClient → LLM gateway → WAN → the cloud site's internal routes → the model server's static route in-regionOn-prem, same ledgerExtra serving capacity, users near that region
Public APIClient → gateway → provider. The gateway swaps the user's identity for the provider key it holds.On-prem, at the provider's priceFrontier quality when a rule or a team's entitlement calls for it

Putting a self-hosted model in front of callers follows the same order on-prem or in the cloud region. The platform team creates a static route, a fixed address that outlives any one endpoint. The serving app is launched against that route, so the endpoint it stands up answers there. The route is then registered with the LLM gateway under an alias, and the alias is what applications call.

Coding agents and desktop tools that talk to a provider directly can be pointed at the same endpoint, so their tokens land on the same ledger instead of on someone's personal provider account.

Routing rules, guardrails and budgets sit behind that alias. The LLM Gateway and Tokenomics Reference Architecture covers them.

08

Compute policy engine

The compute policy engine keeps owned GPUs busy first and spends cloud capacity on purpose. It has two sets of controls, one for GPUs and one for tokens, and both write to the same ledger.

AI Engineering team · resource policy on a compute resourcereservationin use nowlimitreservedborrowed, idle elsewhereReserved is a guarantee, not a fence: when other teams' GPUs sit idle, this team can run past it, up to its limit.If an owner needs a borrowed GPU back, the task holding it is stopped and re-queued at the front. Its checkpoint lets it resume.
Guarantee plus borrowing keeps utilisation high. On-prem GPUs rarely sit idle while work waits. The cloud pool only grows once owned capacity is genuinely full.

GPU controls

Policies give each team a reserved amount and a limit, over the compute resources they're allowed to use. When several teams want the same GPUs, execution priority decides who goes first. Profiles decide the size of the allocation: a GPU fraction, a whole GPU, or several GPUs on one node. Give each compute resource a usage weight, so a fractional GPU counts as that fraction of a GPU-hour.

Token controls

A budget per project, daily, weekly or monthly, ties spend to an outcome with an owner. Per-user limits stop one person running away with it. Rate limits protect shared models. Guardrails are set in the global policy or per AI resource: deny and allow patterns at the gateway's edge, and the NIM Guardrails app for a model-based check of input and output.

Why per project matters: a project is a named piece of work with an owner. Put its GPU-hours and tokens next to its results, and the conversation turns to return on investment rather than whose usage went up.
09

Placement patterns

The scenario here is the first pattern below: on-prem first, cloud for overflow. The same building blocks support other strategies. Each one is a profile's ordered pool links, so changing strategy means reordering links, not moving workloads.

On-prem first, cloud for overflow

Compute resourceon-prem GPUscloud GPUs

The default for most customers. Owned GPUs are always used first, and the cloud absorbs peaks such as quarter-end retrains or a new model launch.

Burn down a cloud commitment

Compute resourcecloud GPUson-prem GPUs

For a committed-spend agreement that has to be used up, or for moving off the cloud gradually as on-prem capacity arrives. Flip the order back later.

Specify capability, not a GPU model

Compute resourcenewest on-prem GPUsprevious generationcloud GPUs

A profile can specify GPU memory rather than a GPU model. When the newest GPUs are busy, an older one with enough memory still qualifies, and cloud is the last resort.

Train on HPC, serve on Kubernetes

Compute resourceSlurm partitionon-prem Kubernetes

Training runs that belong on the cluster don't have to wait for it. The endpoint that serves the result launches from the same catalogue onto Kubernetes.

Sovereign by policy

Compute resourceon-prem Frankfurtcloud eu-central

For EU projects only. A regulated project can only reach in-country pools, and its outputs are written to in-country storage. Only metadata reaches the control plane. A second site in another jurisdiction is just another pool with its own worker daemons: its models and data stay there, and only reports come home.

10

Design considerations for cloud burst

Decide these on purpose before the first burst, rather than finding them out in production.

Cold start is minutes, not seconds

Node boot plus image pull dominates, then model weights. For latency-sensitive work, keep a small warm minimum, pre-bake images, mirror the registry in each region, and put weight and package caches on persistent volumes.

Move compute to data, not data to compute

Egress is billed per gigabyte and large datasets are slow to move. Keep a versioned copy in each burst region, and let the dataset version pin exactly which bytes were used.

Set the output destination per pool

By default every checkpoint travels home to the file server, and each one is billed as egress. Cloud scratch disk disappears at scale-down. Point cloud pools at an in-region bucket, and checkpoint long runs so preemption or spot reclaim costs minutes, not hours.

Tune the idle window

Short windows save money but cause more cold starts. Long windows do the reverse. Set it per pool: short for bursty training, longer for serving and interactive pools.

Reachability runs one way

Cloud worker daemons need outbound HTTPS to the control plane's API and file server (over VPN, private link or a published endpoint), and to the git server, registry and package mirrors. Batch work needs no inbound connection into the cloud. A site that serves endpoints or sessions needs its own internal routes and ingress. Those routes are the only inbound path to a site.

Mind the WAN hop for tokens

Calls to a cloud-hosted model go through the one LLM gateway. Put that gateway near the heaviest callers, and keep chatty, latency-sensitive models close to them.

Keep location out of the name

Users only ever see a compute resource. Its name describes the allocation, never the location. That way IT can reorder pools, add a region or change clouds without anyone changing their code or habits. Offer users only these compute resources, so every task goes through policy.

Keep declared capacity accurate

The scheduler overflows once a pool's declared capacity is used, not by probing the hardware. Keep those numbers true, and retire any compute resource no node serves, or work will wait on it.

Secrets come from vaults, not images

Inject credentials at run time from group vaults. Never bake keys into an image or pass them as a launch parameter, where they would be recorded on the task for anyone who can read it.

Budget at two levels

GPU policies (reserved, limit, priority) and token budgets (project, user, rate) cover different risks. Cloud spend also has hard ceilings: the autoscaler instance's maximum instances, and the resource policy's limit on the cloud compute resource. Set both levels, and review them against the same per-project ledger.

When something fails

When spot capacity is unavailable, the autoscaler falls back to on-demand. When the cloud pool has no VM free, work waits on the compute resource until the autoscaler adds one, up to its maximum instances. If the apps worker daemon that runs the autoscaler is down, no new VMs are added until it is back. Long runs on spot should save checkpoints, so they can resume.

Connections

This table gathers the connections a cloud burst needs. Users sign in through SSO, and agents over MCP through OAuth. Worker daemons authenticate with the credentials they were registered with.

FromToDirectionPurpose
Users, apps and agentsControl plane: UI, API, MCPInto the control plane, HTTPSSend work to compute resources, manage it, read results
Worker daemons, on-prem and cloudControl plane API and file serverOutbound HTTPS from the sitePull work, stream logs and metrics, upload outputs when the output destination is the file server
AutoscalerCloud APIOutbound, from the VPC or from on-premRun, describe and terminate instances, tag them, request spot
UsersThe site's internal routesInto the site: the only inbound path to a siteReach sessions and endpoints running there
LLM gatewayCloud-site models and public model APIsOutbound from on-premRoute model calls. Provider keys stay in the gateway
GPU nodesGit server, registry and package mirrorsOutbound from the nodeClone code, pull images and packages
11

Glossary

Control plane
The Klique server: UI, API and MCP, compute resources and scheduler, policies, identity, vaults, and the metadata and usage ledger. It holds intent and records; the data stays where the work runs.
Klique worker daemon
The small worker process on every GPU node, whether VM, bare metal, Kubernetes or Slurm. It polls the control plane for work over outbound HTTPS, runs it, and reports back.
Compute resource
The target a user sends work to, from any provisioning method. Under the hood it's a queue. It's the only piece of this architecture a user ever sees.
Resource pool
A set of nodes running worker daemons in one place: an on-prem cluster, a Slurm partition, or an autoscaled cloud account.
Profile
The allocation a task receives (a GPU fraction, a whole GPU or several GPUs), linked to one or more pools in priority order.
Resource policy
Which teams may use which compute resources, with a reserved amount, a limit, and an execution priority.
Autoscaler instance
The autoscaler's definition, stored in the control plane: the compute resources to poll, instance types, limits, idle timeout and credentials.
Autoscaler
The running process that creates GPU VMs when work waits on the compute resource it polls, and removes them when they go idle. On Kubernetes, the cloud's own node autoscaler takes this role.
Apps worker daemon
The component that runs autoscalers and app controllers. By default it sits beside the control plane. It can also run on a small instance in the customer's VPC with an IAM role.
Internal routes
The routes to sessions and endpoints at each serving site, with access control. A self-hosted model's fixed address on them is a static route.
LLM gateway
The single endpoint for every model call. It handles identity, access, guardrails, budgets, routing rules, and metering.
Alias
A model name that callers use, such as chat or embed, that IT can point at any model without clients changing.
Output destination
Where a task writes checkpoints, artifacts and models: an in-region bucket or on-prem storage. The control plane stores the pointer.