Cloud
·4 min read·

Next.js on Google Cloud Run: Production Caching, Secrets, and Zero Cold Starts

Main cover illustration for article: Next.js on Google Cloud Run: Production Caching, Secrets, and Zero Cold Starts

In my previous guide, Moving from Vercel Next.js to Google Cloud Run, we walked through setting up standalone Docker builds and deploying to Cloud Run to achieve predictable $0 hosting.

Once your Next.js application is running in a container, the next step is making it truly production-ready:

  1. How do you serve _next/static assets at edge speed without hammering your container?
  2. How do you manage API keys and database credentials securely?
  3. How do you eliminate cold starts when traffic spikes?
  4. How do you automate deployment pipelines with Google Cloud Build?

Here is the architectural blueprint for running high-performance Next.js on Google Cloud Run.


1. Edge Caching & Cloud CDN for Static Assets ⚡

When you run Next.js on Vercel, static assets in _next/static and public/ are served automatically from edge points of presence. On Cloud Run, every uncached request spins up a container CPU cycle.

To prevent container load and ensure sub-50ms asset delivery, configure Cache-Control headers in next.config.ts:

// next.config.ts
import type { NextConfig } from "next";
 
const nextConfig: NextConfig = {
  output: "standalone",
  async headers() {
    return [
      {
        // Cache immutable static bundles for 1 year at the edge
        source: "/_next/static/:path*",
        headers: [
          {
            key: "Cache-Control",
            value: "public, max-age=31536000, immutable",
          },
        ],
      },
      {
        // Cache public images and icons for 24 hours
        source: "/images/:path*",
        headers: [
          {
            key: "Cache-Control",
            value: "public, max-age=86400, stale-while-revalidate=43200",
          },
        ],
      },
    ];
  },
};
 
export default nextConfig;

When placed behind Cloudflare or a Google Cloud Load Balancer with Cloud CDN enabled, static assets are cached at the edge, reducing container requests by over 85%.


2. Managing Secrets with Google Secret Manager 🔐

Never bake .env files or API secrets into Docker images. Instead, store them in Google Secret Manager and mount them into your Cloud Run service at startup.

Step 1: Create the Secret in GCP

echo -n "sk_live_my_super_secret_api_key" | gcloud secrets create STRIPE_API_KEY \
  --data-file=- \
  --replication-policy="automatic"

Step 2: Grant Permissions to the Cloud Run Service Account

PROJECT_ID=$(gcloud config get-value project)
PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")
 
gcloud secrets add-iam-policy-binding STRIPE_API_KEY \
  --member="serviceAccount:${PROJECT_NUMBER}-compute@developer.gserviceaccount.com" \
  --role="roles/secretmanager.secretAccessor"

Step 3: Mount Secrets in the Deployment Command

gcloud run deploy nextjs-blog \
  --image gcr.io/${PROJECT_ID}/nextjs-blog:latest \
  --region us-central1 \
  --set-secrets="STRIPE_SECRET_KEY=STRIPE_API_KEY:latest"

In your Next.js code (process.env.STRIPE_SECRET_KEY), the value is accessible synchronously as a standard environment variable.


3. Eliminating Cold Starts 🚀

Cloud Run scales down to zero instances when idle, saving you money. However, the first request after an idle period experiences a cold start.

Here is how to reduce cold start latency from 4 seconds down to under 300ms:

| Technique | Command / Setting | Impact | |---|---|---| | Standalone Output | output: 'standalone' in Next.js | Container drops from 2.1GB to 120MB | | Startup CPU Boost | --cpu-boost flag | Allocates 200% CPU during container boot | | Minimum Instances | --min-instances=1 | Keeps 1 container warm at all times (optional) | | Concurrency Tuning | --concurrency=80 | Handles up to 80 requests simultaneously per container |

Deploy with startup CPU boost enabled:

gcloud run deploy nextjs-blog \
  --image gcr.io/${PROJECT_ID}/nextjs-blog:latest \
  --region us-central1 \
  --cpu-boost \
  --concurrency=80 \
  --memory=512Mi \
  --cpu=1

4. Automated CI/CD with Cloud Build 🛠️

Instead of deploying manually from your terminal, set up a cloudbuild.yaml file in your repository:

# cloudbuild.yaml
steps:
  # 1. Build Docker image with Kaniko cache
  - name: 'gcr.io/kaniko-project/executor:latest'
    args:
      - '--destination=gcr.io/$PROJECT_ID/nextjs-blog:$COMMIT_SHA'
      - '--destination=gcr.io/$PROJECT_ID/nextjs-blog:latest'
      - '--cache=true'
      - '--cache-ttl=24h'
 
  # 2. Deploy container to Google Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args:
      - 'run'
      - 'deploy'
      - 'nextjs-blog'
      - '--image=gcr.io/$PROJECT_ID/nextjs-blog:$COMMIT_SHA'
      - '--region=us-central1'
      - '--platform=managed'
      - '--allow-unauthenticated'
      - '--cpu-boost'
 
images:
  - 'gcr.io/$PROJECT_ID/nextjs-blog:$COMMIT_SHA'
  - 'gcr.io/$PROJECT_ID/nextjs-blog:latest'

Connect your GitHub repository in the Google Cloud Console under Cloud Build > Triggers. Every push to main automatically builds, tests, and deploys your Next.js application in under 90 seconds.


Conclusion & Architecture Summary 🎯

Running Next.js on Google Cloud Run gives you enterprise-grade infrastructure without runaway bills:

  • Cloud CDN / Cloudflare Cache-Control protects your containers and speeds up static assets.
  • Secret Manager keeps tokens and sensitive credentials secure.
  • Startup CPU Boost eliminates cold starts.
  • Cloud Build automates production deployment with zero manual steps.

Ready to migrate? Check out the initial guide: Moving from Vercel Next.js to Google Cloud Run: A Cost and Architecture Guide.

Photo by Robson Hatsukami Morgan on Unsplash

Part of the Cloud Series

Explore more in-depth guides and real-world architectures in the Cloud series.

View Entire Series

Frequently Asked Questions

How do you handle static asset caching for Next.js on Google Cloud Run?

Pair your Cloud Run service with Google Cloud CDN or Cloudflare. Set immutable Cache-Control headers on static chunks (_next/static) so edge caches serve static assets directly without hitting your container instances.

How do you inject environment variables securely from Google Secret Manager?

Use the --set-secrets flag in the gcloud run deploy command to mount secrets as environment variables directly at runtime, granting the Cloud Run service account the Secret Manager Secret Accessor role.

How can you minimize cold starts in Next.js on Cloud Run?

Keep container images minimal with Next.js standalone mode (under 120MB), enable startup CPU boost with --cpu-boost, and configure --min-instances=1 during peak business hours.

Can you automate Next.js deployments to Cloud Run with Cloud Build?

Yes. Create a cloudbuild.yaml file in your repository and set up a Cloud Build GitHub trigger to build, push to Artifact Registry, and deploy to Cloud Run automatically on every push.

Related Articles


Real Software. Real Lessons.

I share the lessons I learned the hard way, so you can either avoid them or be ready when they happen.

User avatar
User avatar
User avatar
User avatar
+13K

Join 13,800+ developers and readers.

No spam ever. Unsubscribe at any time.

Discussion