Google Announces MultidimPodAutoscaler (MPA) for GKE

Google Announces MultidimPodAutoscaler (MPA) for GKE

Introduction

Google has quietly rolled out a new beta feature for Google Kubernetes Engine (GKE): the MultidimPodAutoscaler, or MPA. Announced in early July 2026, MPA gives GKE users a single custom resource that scales both horizontally and vertically at the same time. 

If you’ve spent any time in Kubernetes, you already know the two usual tools for the job. The Horizontal Pod Autoscaler (HPA) watches a metric like CPU utilization and adds or removes replicas to match demand. The Vertical Pod Autoscaler (VPA) watches historical resource usage and recommends, or automatically applies, better CPU and memory requests for a single Pod template. The catch has always been that running both together on the same workload is risky at best and unsupported at worst. 

MPA is Google’s answer to fill that gap. Rather than reconciling two separate objects, MPA is a single MultidimPodAutoscaler object that adds replicas horizontally based on CPU utilization, while adjusting memory requests vertically, at the same time. Think of it as the intersection of HPA and VPA: HPA’s replica count logic, married to VPA’s resource-request logic. 

How it works

MPA targets a Deployment (or other scalable workload) the same way HPA does: using a scaleTargetRef. You still define your workload’s CPU request yourself, because MPA doesn’t set CPU requests. Once the Deployment exists, you layer a MultidimPodAutoscaler object on top of it that defines:

  • A CPU utilization goal (the horizontal scaling target)
  • Constraints on replica count and memory bounds (the vertical scaling guardrails)
  • An update policy for how recommendations get applied

Here’s a sample Deployment. Note that a CPU request is mandatory, since MPA has nothing to scale horizontally against otherwise:

apiVersion: apps/v1 
kind: Deployment 
metadata: 
  name: php-apache 
spec: 
  selector: 
    matchLabels: 
      run: php-apache 
  replicas: 1 
  template: 
    metadata: 
      labels: 
        run: php-apache 
    spec: 
      containers: 
      - name: php-apache 
        image: us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0 
        ports: 
        - containerPort: 80 
        resources:
          # MPA does not set CPU requests, so you must specify one here 
          limits: 
            cpu: 500m 
          requests: 
            cpu: 200m 

And here’s the accompanying MultidimPodAutoscaler: 

apiVersion: autoscaling.gke.io/v1beta1 
kind: MultidimPodAutoscaler 
metadata: 
  name: php-apache-autoscaler 
spec: 
  scaleTargetRef: 
    apiVersion: apps/v1 
    kind: Deployment 
    name: php-apache 
  goals: 
    metrics: 
    - type: Resource 
      resource: 
        name: cpu 
        target: 
          type: Utilization 
          averageUtilization: 75 
  constraints: 
    global: 
      minReplicas: 1 
      maxReplicas: 5 
    containerControlledResources: [ memory ] 
    container: 
    - name: '*' 
      requests: 
        minAllowed: 
          memory: 1Gi 
        maxAllowed: 
          memory: 2Gi 
  policy: 
    updateMode: Auto 

Goals versus constraints 

It’s worth being precise about the difference between these two sections, because MPA is explicit that constraints always win: 

  • Goals describe what the autoscaler is trying to achieve. In the example above, that’s 60% average CPU utilization per replica. 
  • Constraints describe the boundaries it’s not allowed to cross, such as a hard cap of 5 replicas or a memory ceiling of 2Gi per container. 

If a goal and a constraint conflict, the constraint wins. If CPU utilization is still climbing but you’ve hit maxReplicas, MPA will not scale further, even though the goal isn’t being met. Constraints are a safety rail, not a suggestion.

Where the memory scaling logic comes from

MPA’s vertical scaling (memory only, for now) rides on the same recommender used by GKE’s standalone Vertical Pod Autoscaler. That recommender is, in turn, based on the open source Kubernetes VPA API, but Google is explicit that GKE’s implementation is a separate, proprietary engine “designed for scale” with its own recommender, while retaining the same API surface as the open source project.

What’s not published is exactly how GKE’s recommender differs algorithmically from upstream VPA. Google states that it uses historical usage data, accounts for OOM events with a safety buffer, and produces target/lowerBound/upperBound/uncappedTarget values, but the actual math (percentile calculations, decay weighting, sampling windows, and so on) isn’t public. If you’re the kind of team that likes to know exactly how a number was derived before trusting it in production, that’s a legitimate open question with MPA today, since the answer is essentially “trust the black box.”

Kubex and Multidimensional Autoscaling

MPA is a good idea. It’s also not the only way to get there, and it’s not even necessarily the most mature way to get there today.

The Kubex Automation Engine solves the same problem, and complements HPA directly rather than replacing it: it right-sizes memory requests for HPA-managed workloads, in much the same way as MPA does.

HPA scales by cloning a Pod template into more replicas. It’s very good at reading CPU utilization and scaling out replicas when more are needed. But it has no visibility at all whether the template it’s cloning is well-sized for memory. If your Deployment’s Pod template requests more memory than it actually needs, HPA will happily scale it out 10, 50, or 100 times over, faithfully replicating that waste with every new replica. You end up with a CPU-to-memory ratio that’s completely out of step with what the workload actually consumes, and a bill that grows in lockstep with your replica count.

Kubex addresses this by using historical usage data and a deterministic ML algorithm to continuously tune that CPU-to-memory ratio, so that every replica HPA spins up is appropriately sized rather than an over-provisioned clone. The net effect looks a lot like MPA’s goal (right-sized memory alongside horizontal CPU scaling), just arrived at using the HPA you know and trust instead of a brand new CRD.

A couple of practical differences worth calling out plainly:

  • Maturity. Kubex’s Automation Engine is a shipped, production-proven product. MPA is a beta feature, subject to Google’s Pre-GA terms, “available as is,” with limited support.
  • Portability. MPA is a GKE-only object type (autoscaling.gke.io/v1beta1). It doesn’t exist on EKS, AKS, on-prem clusters, or anywhere else. Kubex offers equivalent right-sizing functionality today, across any Kubernetes distribution or platform, GKE included.

Summary

MPA is a genuinely useful idea, and it’s easy to see why Google built it: unifying HPA and VPA behaviour under one object removes a real pain point, and there’s plenty of room for it to grow, presumably to cover CPU-based vertical scaling too, once it graduates from beta. It’s worth keeping an eye on.

That said, “beta,” “GKE-only,” and “undocumented recommender internals” are three reasons to give pause before betting production workloads on it today. If you want the same outcome: right-sized memory sitting comfortably alongside horizontal CPU scaling, without waiting on a pre-GA feature or locking yourself to a single cloud provider, Kubex’s Automation Engine already does it, today, on whatever Kubernetes you’re running.

Worth a look either way: pull up your own HPA-managed workloads and check how their memory requests actually compare to real usage. Whether you land on MPA, Kubex, or a bit of both, the pattern of “stop paying for over-sized replica templates” is one worth chasing down in your own environment.