---
title: How to migrate from Google Cloud Run to Vercel
description: Move a Cloud Run service or worker to Vercel. Compare runtimes, preserve Google Cloud access, and plan jobs, validation, and production cutover.
url: "https://vercel.com/kb/guide/migrate-cloud-run-to-vercel"
published: 2026-08-11
last_updated: 2026-10-22
authors: Ben Sabic
related_resources:
  - title: "The Complete Guide to Vercel Services"
    url: "https://vercel.com/kb/guide/vercel-services"
    description: "Vercel Services let you deploy multiple frontends and backends in one project on a shared domain. Learn how to define services in vercel.json, route requests by path prefix, and connect services with generated environment variables."
  - title: "Running Docker on Vercel"
    url: "https://vercel.com/kb/guide/docker"
    description: "Learn how to run Docker on Vercel by deploying OCI container images as Vercel Functions, storing them in Vercel Container Registry (VCR), and running containers in Vercel Sandbox."
  - title: "Backends on Vercel: Python, containers, and Daemons"
    url: "https://vercel.com/blog/backends-on-vercel-python-containers-and-daemons"
    description: "Explore how Python, container images, and background workers fit into the Vercel platform."
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

Migrate a Cloud Run HTTP service through Vercel's [framework support](https://vercel.com/docs/frameworks/more-frameworks) or a `Dockerfile.vercel`. The container path stores the built image in Vercel Container Registry and runs it as a [Function on Fluid compute](https://vercel.com/docs/functions/runtimes/container).

Check runtime compatibility and access to Google Cloud dependencies before moving traffic. Continuous pull-based workers can use [Vercel Daemons](https://vercel.com/docs/daemons); run-to-completion jobs need a separate decision about scheduling and execution.

## Should your app move?

Cloud Run services and Vercel container-based Functions both serve HTTP and can scale to zero. Google Cloud resources you retain still need their IAM permissions and network connections after the app moves.

Your HTTP service is a good fit when it:

- Keeps durable state in an external database or storage service
  
- Tolerates scaling to zero without relying on warm instances
  
- Uses local files as temporary working storage
  
- Fits the memory, request, and execution limits of [Vercel Functions](https://vercel.com/docs/functions/limitations)
  

The container path is a poor fit for GPU workloads, a continuously warm HTTP server, or batch tasks that exceed function limits. Custom container images also lack [Secure Compute and Static IP support](https://vercel.com/docs/functions/runtimes/container#limits-and-pricing), so verify connectivity if a downstream system requires fixed egress IPs.

Use the [worker-pool migration steps](#migrate-a-cloud-run-worker-pool-to-a-daemon) to assess queue consumers for Vercel Daemons. Redesign workers that need private inbound connections.

For other container workloads, [compare hosting options by workload](https://vercel.com/i/which-platform-should-host-your-docker-app) before choosing a destination.

## How do Cloud Run concepts map to Vercel?

| Cloud Run                                                                                                 | Vercel                                                                                                |
| --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
| Service (stateless HTTP container, scales to zero by default)                                             | Container image running as a Vercel Function on Fluid compute                                         |
| Artifact Registry (`LOCATION-docker.pkg.dev/PROJECT_ID/REPO_NAME/PATH:TAG`)                               | Vercel Container Registry (`vcr.vercel.com/team-slug/project-slug/my-repository:tag`)                 |
| Deploy a prebuilt image with `gcloud run deploy SERVICE --image IMAGE_URL`                                | Build from source with `vercel deploy` or a connected Git repository                                  |
| `PORT` env var injected into the container, default `8080`                                                | HTTP server on port `80` by default; override with a `PORT` environment variable in project settings  |
| Secret Manager secrets as env vars or mounted volumes                                                     | Secret environment variables in project settings                                                      |
| Cloud Run jobs                                                                                            | Eligible scheduled HTTP tasks can use Cron Jobs; completion and retry behavior need separate handling |
| Worker pool (continuous pull-based background work, configured instance count, no load-balanced endpoint) | [Daemon](https://vercel.com/docs/daemons) declared under the `daemons` key in `vercel.json`           |
| `SIGTERM`, then `SIGKILL` after 10 seconds                                                                | `SIGTERM` with a 30-second grace period before forced termination                                     |
| Source deploys (`gcloud run deploy` without `--image`, Cloud Build)                                       | Framework detection for Express, FastAPI, Flask, Django, Go, Next.js, and more                        |

TLS looks the same from inside the container: Cloud Run terminates TLS and proxies plain HTTP, and Vercel expects a plain HTTP server too.

Still choosing a destination? [Compare Cloud Run alternatives by workload](https://vercel.com/i/cloud-run-alternatives) before starting the migration.

## Before you begin

Have your application source, Cloud Run configuration, and required secret versions available. Install the latest Vercel CLI and ensure you can access the destination team. Container testing also needs the Docker CLI and a running Docker daemon.

From the project root, sign in and [link the directory to a Vercel project](https://vercel.com/docs/cli/link):

```bash
vercel login
vercel link
```

Keep the Cloud Run deployment available while you test the replacement.

### Preserve access to Google Cloud resources

Cloud Run supplies credentials through its attached service account and metadata server. Those credentials do not move with the image. For Google APIs your app keeps using, configure [Workload Identity Federation from Vercel](https://vercel.com/docs/oidc/gcp) and retain the required IAM permissions.

If Cloud Run IAM restricts who can call your service, implement and test authentication and authorization for the Vercel endpoint before cutover. Include service-to-service calls and event producers in that check.

Check network access separately from credentials. [Cloud SQL private IP connections](https://docs.cloud.google.com/sql/docs/postgres/connection-options) and other private VPC resources need a reachable network path. Confirm a supported connection from your chosen Vercel runtime, or keep the workload that needs that connection on Cloud Run.

## Migrate a Cloud Run service in 7 steps

### 1\. Choose framework support or a container

Check Vercel's [framework support](https://vercel.com/docs/frameworks/more-frameworks) before copying your Dockerfile. Express, FastAPI, Flask, Django, Go, and Next.js can deploy from source. Your Cloud Run deployment method does not determine whether you need a container on Vercel.

Follow the framework's entrypoint and dependency instructions. For example, a [FastAPI app](https://vercel.com/docs/frameworks/backend/fastapi) needs an exported application instance in a supported file or a configured entrypoint. Skip the container-specific port and shutdown steps.

To keep a custom container build, copy your Dockerfile to `Dockerfile.vercel` or `Containerfile.vercel` at the project root. Vercel builds and pushes the image, then adds a rewrite that sends traffic to it. Continue with the container settings below.

### 2\. Set the port

Cloud Run defaults to port `8080` and requires the server to listen on `0.0.0.0`. Vercel's container runtime expects port `80` unless you set `PORT` in project settings.

If your server already reads `PORT` at startup, set it to `8080` for the Vercel environments you'll use. Keep listening on `0.0.0.0` and verify the selected port when you test the service.

### 3\. Move Secret Manager secrets to environment variables

Cloud Run can expose Secret Manager values as environment variables or mounted files. Environment variables resolve at instance startup, so Google recommends pinning them to a specific secret version. Mounted secrets can refresh when the app reads the file.

For each value you move, create a [Secret environment variable](https://vercel.com/docs/environment-variables/sensitive-environment-variables) in Vercel and select its target environments. Use the value from the version your app currently relies on. Secret values are write-only after saving.

Change code that reads a mounted secret to read the environment variable. When rotating the credential, update its value in Vercel and [redeploy](https://vercel.com/docs/environment-variables/managing-environment-variables). Changes in Secret Manager will not update the copied value automatically.

### 4\. Update shutdown handling

During scale-in, Cloud Run sends `SIGTERM` and allows 10 seconds before `SIGKILL`. Vercel gives container-based Functions 30 seconds to clean up before forced termination. Keep cleanup within that window and persist unfinished work where another instance can recover it.

Vercel scales down a container-based Function after 5 minutes without traffic in production or 30 seconds in a preview deployment.

### 5\. Adapt scheduled jobs

Cloud Run jobs run finite container tasks and track completion. Use a Vercel cron job for work that fits an HTTP handler and function duration limits. Keep jobs on Cloud Run when their duration or execution requirements don't fit.

For eligible tasks, expose an endpoint and merge a `crons` property into your existing `vercel.json`. This example requests a daily run at 03:00 UTC:

```json
{
  "crons": [
    { "path": "/api/daily-job", "schedule": "0 3 * * *" }
  ]
}
```

Vercel sends an HTTP GET to that path on the production deployment. Check your plan's [scheduling limits and precision](https://vercel.com/docs/cron-jobs/usage-and-pricing) before copying an existing schedule.

Set `CRON_SECRET` and [validate the request's Authorization header](https://vercel.com/docs/cron-jobs/manage-cron-jobs#securing-cron-jobs) before starting work. The cron user agent and schedule header identify the trigger but do not authenticate the caller.

Cloud Run retries failed job tasks by default. Vercel Cron does not retry failed invocations, and scheduled invocations can be missed, duplicated, or overlap. Make the handler safe to repeat, recover work missed since the last successful run, and prevent unwanted overlap. Add any retry mechanism the task requires.

### 6\. Test locally with vercel dev

For a container deployment, run `vercel dev` from the project root with the Docker CLI installed and the Docker daemon running. Check that the HTTP server listens on the configured port. Send the container process a termination signal to test its shutdown handler before deploying.

For framework deployments, follow the framework's local testing instructions. Test application routes and dependency connections with development credentials.

### 7\. Deploy and cut over

For a new Vercel project, the [first deployment is always Production](https://vercel.com/docs/deployments/environments#first-deployment), even if you request a preview. Configure its Production variables for the resources you intend to test. Keep cron jobs [disabled in project settings](https://vercel.com/docs/cron-jobs/manage-cron-jobs#cron-jobs-maintenance) and any Daemons [stopped](https://vercel.com/docs/daemons/managing-daemons#stopping-a-daemon) until the background-work handoff is ready.

Deploy with `vercel deploy` or a connected Git repository. For the container path, Vercel builds the image and pushes it to [Vercel Container Registry](https://vercel.com/docs/container-registry).

After the first deployment, non-production branches and `vercel deploy` without `--prod` create previews. Production-branch commits and `vercel deploy --prod` deploy to Production.

Test the generated URL with representative requests. Verify access control, Google API and database connections, and any webhook or event-producer calls. Check runtime logs and response times before moving traffic.

When the production deployment is ready, [add your domain](https://vercel.com/docs/domains/working-with-domains/add-a-domain) and apply the DNS records shown in the dashboard. Callers using the Cloud Run `run.app` URL must be updated separately. Coordinate the scheduler and worker switch so the two platforms do not process the same work unintentionally.

Keep the Cloud Run service and previous DNS records available through validation. If you need to roll back, restore traffic to Cloud Run and reverse the background-work handoff. Check writes made after cutover before switching back; restoring DNS does not undo data changes.

## Migrate a Cloud Run worker pool to a Daemon

Cloud Run worker pools run continuous pull-based tasks such as Kafka and Pub/Sub consumers. They have no load-balanced URL; you set the instance count.

On Vercel, these processes can run as [Daemons](https://vercel.com/docs/daemons) alongside the app in the same project. Daemons are in Public Beta on all plans, subject to [plan limits](https://vercel.com/docs/daemons/limits).

Vercel Daemons initiate outbound connections and [do not accept inbound HTTP or TCP traffic](https://vercel.com/docs/daemons/limits#unsupported-features). Cloud Run worker pools can receive private connections through [Direct VPC ingress](https://docs.cloud.google.com/run/docs/overview/what-is-cloud-run), so redesign any inbound dependency before moving it.

Keep the worker's existing queue client and a compatible broker. For example, a Redis-backed BullMQ worker still needs Redis after moving to Vercel. To adopt [Vercel Queues poll mode](https://vercel.com/docs/queues/poll-mode), integrate its SDK as a separate change.

Put the worker's source and `Dockerfile` in `worker/`. Its `ENTRYPOINT` or `CMD` must start the worker process. If Cloud Run overrides that command, carry the intended startup command into the image or the Daemon's [`command`](https://vercel.com/docs/daemons/config-reference#command) [setting](https://vercel.com/docs/daemons/config-reference#command).

Test the image locally with Docker and development credentials. Daemons run only in Production during the beta, and `vercel dev` does not start them. Use the [local testing instructions](https://vercel.com/docs/daemons#local-development) before connecting to a live queue.

Add the worker under `daemons` in `vercel.json`. The `root` path is relative to that file, and `entrypoint` is relative to `root`. Vercel builds the image for Linux `amd64` and pushes it to Vercel Container Registry.

```json
{
  "daemons": {
    "worker": {
      "root": "worker/",
      "entrypoint": "Dockerfile",
      "instances": { "iad1": 0 }
    }
  }
}
```

The example keeps the worker stopped when no scaling override is set. To start two instances, set `iad1` to `2` and deploy to Production.

[Existing scaling overrides](https://vercel.com/docs/daemons/managing-daemons#scaling-from-the-dashboard) take precedence over `vercel.json`. Clear or adjust them if they conflict with the intended count.

When a deployment becomes Production, Vercel starts its Daemons and gracefully stops the previous version. It restarts instances that exit or crash.

Old and new versions can overlap during rollout, so their queue messages and database changes must remain compatible. On `SIGTERM`, stop fetching work and drain active tasks. The default grace period is 30 seconds; [`terminationGracePeriodSeconds`](https://vercel.com/docs/daemons/config-reference#terminationgraceperiodseconds) can extend it. Make unfinished work eligible for retry through the queue's acknowledgment or lease mechanism.

## What doesn't map from Cloud Run

- Cloud Run jobs. Cron can schedule HTTP work that fits function limits, but it does not preserve Cloud Run's task execution or retry behavior. Keep incompatible batch jobs on Cloud Run, or redesign how they execute.
  
- Warm HTTP instances. Container-based Functions scale down automatically after idle periods. Applications that require an HTTP instance to remain running need to reassess that requirement.
  
- Persistent and mounted volumes. Cloud Run's default writable filesystem is ephemeral, but [Cloud Storage and NFS mounts](https://docs.cloud.google.com/run/docs/configuring) can expose persistent external data. Inventory the paths your app reads and writes. Replace mounted-file access with a supported storage API or database connection, and migrate data separately if you change storage providers. Handle secret mounts as described in step 3.
  
- Fixed egress IPs. Secure Compute and Static IPs are not supported with custom container images. If a downstream system allowlists your Cloud Run egress, verify a supported access path before cutting over.
  
- Sidecar containers. Vercel Services do not preserve Cloud Run's co-located sidecar topology. Independent HTTP components can become separate [services](https://vercel.com/docs/services) with [service bindings](https://vercel.com/docs/services/bindings) for internal calls. Add public rewrites only for components that external clients need to reach. Components that require shared local files or localhost access need an architecture change.
  

For log-forwarding sidecars, write application logs to `stdout` and `stderr` and review [Vercel logging](https://vercel.com/docs/functions/runtimes/container#observability). Splitting the process into a service does not preserve access to the original container's log files.

## Frequently asked questions

### Does Vercel run my container the way Cloud Run does?

Vercel can run a stateless HTTP container as a Function. Configure its server for port `80`, or set `PORT` in project settings to match the port it already uses. Cloud Run defaults to `8080`.

During scale-in, Vercel allows 30 seconds after `SIGTERM`, compared with Cloud Run's 10 seconds. Check the [Function limits](https://vercel.com/docs/functions/limitations) and the app's Google Cloud dependencies before moving traffic.

### What replaces min instances on Vercel?

Container-based Functions scale down after 5 minutes without traffic in production and 30 seconds in preview deployments. Plan for the next request to reach a new instance after scale-in. If your app requires a continuously warm HTTP instance, reassess that requirement before migrating.

### What happens to my Cloud Run jobs?

Scheduled Cloud Run work can move to a Vercel cron-triggered HTTP handler when it fits function limits. Preserve the task's authentication and recovery requirements: Vercel Cron does not retry failures, and the handler must tolerate missed or repeated invocations. Keep jobs on Cloud Run when their duration or execution model does not fit.

### What happens to my Cloud Run worker pools?

Pull-based worker pools can move to Vercel Daemons when they use a compatible queue backend and need no inbound HTTP or TCP connections. Configure their source directory, Dockerfile, and regional instance counts under `daemons` in `vercel.json`. Test the worker image with Docker locally because Daemons run only in Production during the beta.

### Can I keep my images in Artifact Registry?

You can keep Artifact Registry images for workloads that still use them. If you choose the container path, Vercel builds your application's `Dockerfile.vercel` and stores the deployment image in Vercel Container Registry.

Copying an existing image into VCR is a separate registry operation. It does not replace the source deployment steps above.

### How do Secret Manager secrets move to Vercel?

Copy the required values into Vercel Secret environment variables and update code that reads mounted secret files. Select the appropriate deployment environments, then redeploy. Later Secret Manager changes do not update those copied values automatically, so include Vercel updates and redeployment in your rotation process.

## Related resources

- Migrate to Vercel from [Fly.io](https://vercel.com/kb/guide/migrate-fly-io-to-vercel), [Railway](https://vercel.com/kb/guide/migrate-railway-to-vercel), or [Render](https://vercel.com/kb/guide/migrate-render-to-vercel)
  
- [Does Vercel support Docker deployments?](https://vercel.com/kb/guide/does-vercel-support-docker-deployments)
  
- [How do I migrate images from GHCR to VCR?](https://vercel.com/kb/guide/migrate-ghcr-to-vcr)
  
- [Vercel Daemons documentation](https://vercel.com/docs/daemons)
  
- [The Complete Guide to Vercel Daemons](https://vercel.com/kb/guide/vercel-daemons)
  
- [Run any Dockerfile on Vercel](https://vercel.com/blog/dockerfile-on-vercel)
  
- [7 ways to use Docker containers on Vercel](https://vercel.com/i/7-ways-to-use-docker-containers-on-vercel)
  
- [Cloud Run container runtime contract](https://docs.cloud.google.com/run/docs/container-contract)

## Related Resources

- [The Complete Guide to Vercel Services](https://vercel.com/kb/guide/vercel-services): Vercel Services let you deploy multiple frontends and backends in one project on a shared domain. Learn how to define services in vercel.json, route requests by path prefix, and connect services with generated environment variables.
- [Running Docker on Vercel](https://vercel.com/kb/guide/docker): Learn how to run Docker on Vercel by deploying OCI container images as Vercel Functions, storing them in Vercel Container Registry (VCR), and running containers in Vercel Sandbox.
- [Backends on Vercel: Python, containers, and Daemons](https://vercel.com/blog/backends-on-vercel-python-containers-and-daemons): Explore how Python, container images, and background workers fit into the Vercel platform.

## More Vercel Services guides

- [How to use Vercel Container Registry](/kb/guide/how-to-use-vercel-container-registry): Push, store, and pull OCI container images with Vercel Container Registry, then deploy them to Vercel Functions and Vercel Sandbox.
- [How to migrate from Fly.io to Vercel](/kb/guide/migrate-fly-io-to-vercel): Move an app from Fly.io to Vercel. Map configuration, choose Functions or Daemons, plan persistent storage, and verify the production cutover.
- [Running Docker on Vercel](/kb/guide/docker): Learn how to run Docker on Vercel by deploying OCI container images as Vercel Functions, storing them in Vercel Container Registry (VCR), and running containers in Vercel Sandbox.