How to Move a PaaS App to GKE Without Hiring a DevOps Team
A practical, step-by-step path for moving an app off Heroku, Render, Railway, Fly.io or App Engine onto Google Kubernetes Engine - what you actually have to rebuild, how long it takes, what it costs per month, and how small teams run GKE without a dedicated DevOps hire.
You can migrate a PaaS app to GKE without a DevOps hire, but only by replacing the PaaS with a platform layer instead of a person. The container usually runs unchanged. Routing, TLS, secrets, the database, release migrations, logs, autoscaling and rollback - roughly 13 primitives - all have to be rebuilt. That list is the migration.
The sequence is eight ordered steps: inventory the PaaS config, build an image into Artifact Registry, provision a GKE Autopilot cluster plus Cloud SQL on private IP, migrate data, deploy web/worker/cron workloads, wire the Gateway API with Google-managed certificates, dual-run with DNS TTL at 60 seconds, then decommission after one incident-free week. Only the database cutover is irreversible.
Choose GKE Autopilot, not Standard, if you have no Kubernetes engineers. Google provisions, patches and upgrades the nodes, applies hardened defaults, and bills you for pod CPU/memory requests rather than whole reserved nodes - and its SLA covers your pods, not just the control plane.
Realistic effort: one containerized web app plus Postgres is a 1-3 week project for a competent full-stack engineer; a multi-service app with workers, cron jobs and file storage is 1-3 months DIY. An internal developer platform on top of your own cluster compresses the platform half of that to days.
Be honest about the alternatives: if your app is stateless HTTP and fits Cloud Run's 60-minute request-timeout and instance limits, Cloud Run is less work than GKE; and below roughly $500/month of PaaS spend, staying put is the correct financial call once you price the engineer-weeks.
Every few weeks I talk to a founding engineer who has outgrown their PaaS and been told the same thing: "if you want Kubernetes, you need a DevOps hire first." I have spent 15 years in cloud infrastructure and interviewed more than 200 CTOs, and that advice is mostly wrong. The application is the easy part. A container that booted on Heroku, Render or Railway boots on Google Kubernetes Engine with no code changes. The work is rebuilding the dozen-odd managed services your PaaS quietly ran on your behalf.
So let me walk through exactly what that means - what breaks, what it costs, how long it takes, and how a small team runs GKE without putting someone on call at 3am.
What actually breaks when you move an app off a PaaS to GKE?
Your application code almost never breaks. What breaks is the roughly 13 things the PaaS silently did for you: HTTP routing, TLS issuance and renewal, config injection, the managed Postgres, release-phase migrations, log aggregation, metrics, autoscaling, cron scheduling, static egress IPs and one-click rollback. That replacement list is the migration, not Kubernetes itself.
A PaaS is not a runtime. It is about fifteen managed services wearing one price tag. When you leave, you unbundle them and own each one.
A few things teams forget until cutover day:
Ephemeral filesystem assumptions. PaaS dynos are ephemeral too, but local-disk habits leak in. Anything written to local disk is gone on restart.
SIGTERM handling and terminationGracePeriodSeconds. Kubernetes sends SIGTERM on rollout. If your app ignores it, you drop in-flight requests.
Readiness vs liveness probes. A wrong readiness path means the load balancer sends traffic to a pod that is not ready, or restarts a healthy one.
A static outbound IP. If a partner allowlists your egress IP, you need Cloud NAT to pin one.
On the build side, the "we have no Dockerfile" objection disappears in an afternoon. Cloud Build with Cloud Native Buildpacks (the Paketo/Google buildpacks) reproduces the buildpack experience your PaaS used and pushes the image straight to Artifact Registry. No hand-written Dockerfile required.
The one thing that genuinely changes semantics: a PaaS gives you a single opinionated router per app. On GKE you now own the load balancer, its health checks and the certificate lifecycle. That ownership is real, and it is why people reach for the DevOps hire.
PaaS concept
GKE equivalent
Who manages it
Web process / dyno
Deployment + Service
You / an internal developer platform
Background worker
Separate Deployment
You / platform
Cron / scheduler
CronJob
You / platform
Release-phase migration
Job or initContainer
You / platform
Router + TLS
Gateway API or Ingress + Google-managed certificate
You (Google issues the cert)
Env vars / secrets
Secrets/ConfigMaps or Secret Manager
You / platform
Postgres add-on
Cloud SQL or AlloyDB
Google (managed service)
Redis add-on
Memorystore
Google
Logs
Cloud Logging
Google
Metrics
Cloud Monitoring / Managed Service for Prometheus
Google
Autoscaling
HorizontalPodAutoscaler
You / platform
Rollback
kubectl rollout undo or your CD tool
You / platform
Preview environments
(none native)
Platform, or you build it
Static egress IP
Cloud NAT
You / platform
Should you use GKE Autopilot or GKE Standard if you have no Kubernetes engineers?
Use GKE Autopilot. It removes the three tasks that genuinely need a full-time Kubernetes operator - node provisioning, node upgrades, and capacity planning/bin-packing - bills on the CPU, memory and ephemeral storage your pods request, and carries an SLA that covers both the control plane and the compute running your pods. Standard is the right answer only for a narrow set of cases.
Per Google's own Autopilot overview, in Autopilot mode Google manages your nodes, scaling, security configuration and bin-packing, automatically applies node security patches, and the SLA "covers both the control plane and the compute capacity used by your Pods." On Standard, the SLA covers the control plane and you own the nodes.
The cost model is different in a way that matters for small teams. On Autopilot you pay per pod request - roughly $0.0445 per vCPU-hour and $0.0049225 per GiB of memory-hour for general-purpose pods in us-central1 - with no reserved nodes sitting idle. Every cluster, Autopilot or Standard, also pays a flat $0.10 per cluster per hour management fee, and each billing account gets a $74.40 monthly credit that covers one cluster's management fee. You pay that one cluster fee whether you run 3 pods or 300.
When Standard is still correct: privileged node agents (some eBPF security tooling), custom kernels or machine families, and very spiky batch workloads you want on Spot node pools. If none of that describes you, a team under roughly 20 engineers with no Kubernetes operations experience should start on Autopilot and never create a node pool.
One job stays on your calendar either way. Kubernetes supports each minor version for about 14 months, and the OSS project ships three minor versions a year, so cluster upgrades are a scheduled event a few times a year whether or not someone owns them.
GKE Autopilot
GKE Standard
Who provisions nodes
Google
You
Who patches / upgrades nodes
Google
You
Billing unit
Per-pod CPU/memory/storage requests
Per reserved node
Security defaults
Hardened by default
You configure
Customization limits
No privileged pods, limited host access/DaemonSets
Full node control
SLA scope
Control plane + pods
Control plane only
Est. ops hours / month
Low (upgrades auto-managed)
Meaningful (nodes are yours)
Best for
Teams with no K8s operators
eBPF agents, custom kernels, Spot batch
What is the step-by-step migration plan from a PaaS to GKE?
Here is the full runbook in eight ordered steps, and the database cutover is the only irreversible one. Everything before it can be undone by deleting a namespace, which is exactly why you build the entire GKE stack before you touch production traffic.
Inventory (1-2 days, reversible). Export every process type, env var, add-on, cron schedule, custom domain, certificate, webhook and outbound integration into one file. This document is the acceptance test for the whole migration, and it is the step teams skip.
Container image (hours to 1 day, reversible). Build with a Dockerfile or Cloud Native Buildpacks via Cloud Build, push to Artifact Registry. Verify it boots locally with the exact production env vars before going further.
Provision (2-5 days, reversible). A GKE Autopilot cluster, an Artifact Registry repo, Cloud SQL for PostgreSQL on a private IP, Secret Manager, and Cloud NAT for a static egress IP. Use Terraform if you want it reproducible and reviewable. This is where DIY weeks disappear.
Data (1 day to 2 weeks, partly irreversible). For datasets under roughly 50 GB, pg_dump/pg_restore inside a short maintenance window. For near-zero downtime, Database Migration Service, which supports continuous migration from an external PostgreSQL source. Time a full restore before cutover day - that measured number, not a guess, sets your maintenance window.
Workloads (3-7 days, reversible). A Deployment for web, a separate Deployment per worker type, a CronJob per scheduler, a Job or initContainer for release-phase migrations, and a HorizontalPodAutoscaler for scaling. Set resource requests from observed usage, not from a blog post - wrong requests are the number-one cause of post-migration OOMKills.
Traffic (2-3 days, reversible). GKE Gateway API (or Ingress) with Google-managed certificates, load balancer health checks matched to your readiness probe path, and DNS TTL lowered to 60 seconds at least 48 hours in advance.
Dual-run (3-7 days, reversible). Run the PaaS and GKE side by side against real traffic, compare error rate and p95 latency, and keep the PaaS app warm as the rollback target.
Decommission (irreversible, do it last). Only after one full billing cycle and one incident-free week, with a backup restore verified in the new environment.
How long does a PaaS to GKE migration take, and is GKE actually cheaper?
A single containerized web app with one Postgres database is a 1-3 week project for a competent full-stack engineer; a multi-service app with workers, cron jobs, file storage and third-party IP allowlists is 1-3 months done DIY. On run cost, GKE typically wins above roughly $500-1,000/month of PaaS spend and loses below it once you price the engineer-weeks.
Let me use one consistent workload so the numbers reconcile: 2 web pods at 1 vCPU / 2 GB, 1 worker pod, 1 Postgres at 2 vCPU / 8 GB with HA and 100 GB SSD, and about 500 GB/month of egress.
The three line items migration budgets always forget are all on the GKE side:
The GKE cluster management fee - $0.10/hour, about $73/month, largely offset by the $74.40 monthly credit.
The load balancer - a global forwarding rule at $0.025/hour plus $0.008/GiB processed.
Internet egress - $0.12/GB for the first TB on the default Premium tier, so ~500 GB is about $60/month.
The hidden DIY cost is bigger than any of those. A US DevOps/platform engineer runs about a $150,000 median total comp, so one engineer-week is roughly $2,900. A 1-3 month DIY platform build is $12,000-36,000 of salaried time before you count recurring upgrades, certificate and secret hygiene, and the on-call.
The hidden cost of staying is real too: the PaaS compute premium at scale, no private networking to your own data, compliance ceilings, and exposure to vendor pricing changes. And there is a BYOC argument with a number behind it - Google committed use discounts run up to 37% for a 1-year and 55% for a 3-year commitment, and they only accrue in your own billing account. A platform that resells you capacity cannot pass those through.
Say it plainly: below a few hundred dollars a month of spend, migrating is a worse deal than staying on the PaaS. Credibility matters more than conversion here.
Infra figures are estimates derived from the linked list prices for the workload above; your mix will move them.
Can you run GKE without a dedicated DevOps team - and what does that actually require?
Yes, and thousands of small teams do it - but only by giving the work an owner rather than hoping it disappears. Five jobs still have to get done every month: GKE cluster upgrades, certificate renewal, resource-request and scaling tuning, secret rotation, and incident debugging. Decide who or what owns each of those five before you migrate, and the DevOps hire becomes optional.
You have three honest options.
Option A - DIY GKE plus glue. Terraform, Helm or Kustomize, Argo CD or GitHub Actions, cert-manager or managed certificates, external-secrets. Maximum control, and you now maintain a platform that someone owns at 3am.
Option B - stay serverless where you can.Cloud Run is genuinely less work than GKE for stateless HTTP. Its documented ceilings - a 60-minute maximum request timeout (5 minutes default) and up to 1,000 concurrent requests per instance - are the self-selection test. If your app fits inside them, Cloud Run beats GKE. If it is long-running, stateful or non-HTTP, it does not fit.
Option C - an internal developer platform on top of your own GKE cluster. Developers keep git-push deploys, per-PR preview environments, per-environment RBAC and one-click rollback, while the platform owns cluster lifecycle, upgrades and infra wiring.
The honest trade-off of each comes down to lock-in surface, monthly cost, flexibility ceiling, learning curve, and what happens if the vendor disappears - specifically, does standard Kubernetes remain underneath so you can leave without a rewrite?
No matter which option you pick, a small team still owns application observability, cost ceilings and budget alerts, verifying that database restores actually work, and the security of its own dependencies.
The data backs the "give it an owner" framing. In the 2024 CNCF survey, Kubernetes hit 80% production use, and complexity and organizational factors - not raw technical capability - are now the top barriers, with complexity named by about 34% of respondents. And the 2024 DORA report found internal developer platforms raised individual productivity by 8% and team productivity by 10%, while flagging a short-term dip in throughput and stability as teams adopt them. Kubernetes does not need a DevOps engineer. It needs an owner for five recurring jobs, and an internal developer platform can be that owner.
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own GCP, AWS, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.
Which platforms let a small team run GKE without Kubernetes expertise?
Six options are worth evaluating - Qovery, Northflank, Porter, Coolify, Cloud Run and plain GKE with Argo CD - and they separate on three questions: does it deploy into your own Google Cloud project, does it perform the GKE cluster upgrades for you, and does it cover non-production with preview environments? Answer those three before you look at pricing, because only the first two decide whether you still need a DevOps hire.
Qovery deploys into your own GCP project, performs managed cluster upgrades, gives you git-push deployments, preview/ephemeral environments per pull request, environment auto-stop for non-production, per-environment RBAC, and databases backed by managed cloud services. The cloud bill and the committed use discounts stay in your name. The same path works identically on AWS, Azure, Scaleway or an existing Kubernetes cluster - I will mention that once and get back to GKE.
Northflank and Porter are also BYOC-capable on GCP. Both let you run in your own account; they differ in developer experience and in how much of the cluster lifecycle they take on versus leave to you. Evaluate them on the same three questions.
Coolify is open-source and cheap, but you operate the control plane yourself, so it does not remove the operations job at scale.
Cloud Run is the least operations of all six, but it is not Kubernetes and it is constrained for stateful, long-running or non-HTTP workloads.
Plain GKE + Argo CD is maximum control and maximum ownership. It is the right choice when you already have Kubernetes expertise in-house, and the wrong one when you are reading this article.
Paste this five-question checklist into a doc and run every candidate through it:
Does it run in my own cloud account (BYOC)?
Who upgrades the cluster?
Is standard Kubernetes underneath, so I can leave without a rewrite?
Does it cover non-production too (preview environments)?
Does it have per-environment RBAC?
Qovery
Northflank
Porter
Coolify
Cloud Run
DIY GKE + Argo CD
Runs in your own GCP account (BYOC)
Yes
Yes
Yes
Yes (your VMs)
Yes (managed)
Yes
Performs GKE cluster upgrades
Yes
Yes
Partial
No
N/A
No (you do)
Git-push deploy
Yes
Yes
Yes
Yes
Yes
Via CD setup
Per-PR preview environments
Yes
Yes
Yes
Limited
No
You build it
Environment auto-stop
Yes
Partial
Partial
No
Scales to zero
You build it
Per-environment RBAC
Yes
Yes
Yes
Limited
IAM
You build it
Managed databases
Yes (cloud services)
Yes
Yes
Self-run
External
External
Standard K8s underneath (exit path)
Yes
Yes
Yes
No (not K8s)
No
Yes
Est. ops hours / month
Low
Low
Low-Med
Medium
Very low
High
Pricing model
Per-resource / seat
Per-resource
Per-resource
Open-source
Per-request
Free tool, your time
What is the lowest-risk cutover sequence on migration day?
The lowest-risk sequence is fixed, and you write it down before the day: freeze writes or enable replication, run the final sync, scale the PaaS web process to zero, run migrations as a Kubernetes Job, flip DNS, verify against thresholds agreed in advance, then leave the entire PaaS stack intact for seven days. Anything not on that list is improvisation.
Pre-flight checklist. DNS TTL at 60 seconds for 48 hours, a backup taken and a restore timed, a written rollback runbook, a drafted status-page update, and an agreed feature freeze.
Zero-downtime vs maintenance window. For a read-heavy app with a small database, a 10-minute window is cheaper than building a replication pipeline. For write-heavy apps, global users or contractual SLAs, build the replication pipeline with Database Migration Service instead.
Verification set. Synthetic checks on the critical path, p95 latency against the PaaS baseline, error-rate delta, worker queue depth, and one real end-to-end user transaction including auth and payment.
Rollback triggers, defined in advance with numbers. Error rate above X%, replication lag above Y seconds, auth failures, or queue depth not draining within Z minutes. Pick real values before you start.
Post-cutover week. Watch cost daily, watch pod restarts and OOMKills from wrong resource requests, confirm every CronJob actually fired, and confirm backups ran in the new environment. Then, and only then, delete the PaaS app.
How do I do this with Qovery from Claude Code or Cursor?
You can drive the whole GKE setup and deployment from your coding agent: install the Qovery Agent Skills once, then ask the agent in plain language to deploy into your own Google Cloud project. Here are the exact commands, in order, and what each one asks you to approve.
Install the skills once for every compatible agent (Claude Code, Cursor, Codex, OpenCode, Gemini CLI):
Add the Qovery MCP Server to Claude Code (OAuth, read-only by default):
BASH
claude mcp add --transport http qovery https://mcp.qovery.com/mcp --callback-port 4242
Enable write access only when you explicitly want the agent to change things (also requires write access enabled in the Qovery Console):
BASH
claude mcp add --transport http qovery "https://mcp.qovery.com/mcp?read_write=true" --callback-port 4242
Which skill does what: qovery-onboard connects the GCP account and cluster, qovery-deploy ships the app, qovery-preview sets up per-PR environments, qovery-troubleshoot debugs a failing deploy, qovery-optimize cuts cost, plus qovery-speedup and qovery-terraform. The MCP Server operates what already exists.
Then the prompt is plain English:
The agent asks you to approve the things that matter before it acts: cloud credentials, cluster creation, and every write operation. Read access is the default; nothing changes your infrastructure without an explicit yes. Full walkthrough is in the AI agent quickstart and the Claude Code integration page.
How do I migrate a PaaS application to GKE without hiring a dedicated DevOps team?
Replace the PaaS with a platform layer, not a person. The container runs unchanged; the roughly 13 primitives the PaaS managed (routing, TLS, Postgres, secrets, migrations, logs, autoscaling, rollback) get rebuilt on GKE, and an internal developer platform on your own cluster can own the five recurring jobs (upgrades, certs, tuning, secret rotation, incidents) that would otherwise justify a hire.
Should I use GKE Autopilot or GKE Standard for a small engineering team?
Use GKE Autopilot. Google provisions, patches and upgrades the nodes, bills you per pod request rather than per reserved node, and the SLA covers your pods, not just the control plane. Standard only wins for privileged node agents, custom kernels/machine families, or spiky Spot batch.
How long does a Heroku, Render or Railway migration to GKE take?
A single web app plus Postgres is a 1-3 week project for a competent full-stack engineer. A multi-service app with workers, cron jobs, file storage and IP allowlists is 1-3 months DIY. An internal developer platform compresses the platform half of that work to days.
Is GKE actually cheaper than a PaaS like Heroku, Render or Railway?
Usually only above roughly $500-1,000/month of PaaS spend. GKE run cost includes the cluster fee, the load balancer and egress, and below a few hundred dollars a month the engineer-weeks to build the platform (about $2,900/week at a $150k median comp) make staying on the PaaS the correct financial call.
Can I migrate my PaaS Postgres database to Cloud SQL with zero downtime?
Near-zero, yes. Database Migration Service supports continuous migration from an external PostgreSQL source, so you replicate while the old database stays live and cut over in seconds. For datasets under roughly 50 GB, a timed pg_dump/pg_restore in a short maintenance window is simpler. Always time a full restore before cutover day.
Should I use Cloud Run instead of GKE for my PaaS migration?
If your app is stateless HTTP and fits Cloud Run's documented limits - a 60-minute maximum request timeout and up to 1,000 concurrent requests per instance - then yes, Cloud Run is less work than GKE. If it is long-running, stateful, or non-HTTP, GKE is the better fit.
The application was always the easy part. Give the five recurring jobs an owner, and GKE stops needing a DevOps hire.
Alessandro leads product at Qovery. He drives the changelog, roadmap, and product strategy - turning customer feedback into platform capabilities.
Next step
Ship faster on infrastructure you control.
Qovery gives your team self-service deployments on your own GCP, AWS, Azure, or Scaleway account - or your existing Kubernetes cluster. Start deploying in under 10 minutes.