Blog Post

Apps on Azure Blog
6 MIN READ

Heroku Set the Standard. We're Just Removing the Ceiling

simonjj's avatar
simonjj
Icon for Microsoft rankMicrosoft
Mar 19, 2026

A real Node.js + Redis migration in 90 minutes — plus the serverless GPUs and AI-native

For a generation of developers, Heroku was where it clicked — the moment you realized shipping software didn't have to mean fighting infrastructure. Push your code, get a URL, focus on your product. That idea changed an industry, and a lot of us built our first real apps on it.

 

Now that Heroku has entered sustaining engineering — no new features, no new enterprise contracts — it's time to think about what's next.

Azure Container Apps was built on that same developer-first instinct: ship code, not infrastructure. But it doesn't stop where Heroku stopped. Scale-to-zero pricing, event-driven autoscaling, built-in microservice support, serverless GPUs, and an active roadmap mean the platform grows with your application — from a simple web app today to an AI-native service tomorrow.

 

I migrated a real Heroku app to Container Apps to pressure-test the experience. Here's what I learned, what to watch out for, and how you can do it in an afternoon.

 

Why Container Apps is the natural next chapter

The philosophy carries over directly. Where Heroku had `git push`, Container Apps has:

az containerapp up --name my-app --source . --environment my-env

One command. If you have a Dockerfile, it builds and deploys your app directly. No local Docker install, no manual registry push — code in, URL out. That part didn't change.

 

The concept mapping is tight:

Heroku
Azure Container Apps
DynoContainer App replica
Procfile process typesSeparate Container Apps
Heroku add-onsAzure managed services
Config varsEnvironment variables + secrets
`heroku run` one-off dynosContainer Apps Jobs
Heroku PipelinesGitHub Actions
Heroku SchedulerScheduled Container Apps Jobs

 

But Container Apps goes further than Heroku ever did — KEDA-powered autoscaling from any event source, Dapr for service-to-service communication, traffic splitting across revisions for safe rollouts, and scale to zero so you stop paying when nothing's running.

What a real migration looks like

I took a Node.js + Redis todo app from Heroku and moved it to Container Apps. The app is intentionally boring — Express server, Redis for storage, one web process. This is roughly what a lot of Heroku apps look like, and the migration took about 90 minutes end-to-end (most of that waiting for Redis to provision).

 

Step 1: Export what you have

heroku config --json --app my-heroku-app > heroku-config.json
heroku apps:info --app my-heroku-app
heroku addons --app my-heroku-app

You want three things: your environment variables, your add-on list, and your app metadata. The config export is the most important one — it's every secret and connection string your app needs.

Step 2: Create the Azure backing services

For each Heroku add-on, create the Azure equivalent. Here are the common ones:

Heroku add-on
Azure service
CLI command
Heroku PostgresAzure Database for PostgreSQLaz postgres flexible-server create
Heroku RedisAzure Cache for Redisaz redis create
Heroku SchedulerContainer Apps Jobs
az containerapp job create
SendGridSendGrid via Marketplace(Portal)

 

For my todo app, I needed Redis:

az redis create \
--name my-redis \
--resource-group my-rg \
--location swedencentral \
--sku Basic --vm-size c0

One thing to know: Azure Cache for Redis takes 10–20 minutes to provision. Heroku's Redis add-on takes about two minutes. Budget the time.

Step 3: Containerize

If you don't have a Dockerfile, write one. For a Node app this is about 10 lines:

FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 8080
CMD ["node", "server.js"]

 

Don't have a Dockerfile? Point GitHub Copilot at the migration repo and it will generate one for your stack — Node, Python, Ruby, Java, or Go. The repo includes templates and a containerization skill that inspects your app and produces a production-ready Dockerfile.

Step 4: Build, push, deploy

I used Azure Container Registry (ACR) for the build. No local Docker install needed.

az acr create --name myacr --resource-group my-rg --sku Basic
az acr build --registry myacr --image my-app:v1 .

 

Then create the Container App:

az containerapp create \
--name my-app \
--resource-group my-rg \
--environment my-env \
--image myacr.azurecr.io/my-app:v1 \
--registry-server myacr.azurecr.io \
--target-port 8080 \
--ingress external \
--min-replicas 1

Step 5: Wire up the config

This is where Heroku's `config:get` maps to Container Apps' secrets and environment variables. One gotcha I hit: you have to set secrets before you reference them in environment variables. If you try to do both at once, the deployment fails.

# Set the secret first
az containerapp secret set \
--name my-app \
--resource-group my-rg \
--secrets redis-url="rediss://:ACCESS_KEY@my-redis.redis.cache.windows.net:6380"

# Then reference it
az containerapp update \
--name my-app \
--resource-group my-rg \
--set-env-vars "REDIS_URL=secretref:redis-url"

Step 6: Verify and cut over

Hit the Azure URL, test your routes, check that data flows through the new Redis instance. When you're satisfied, update your DNS CNAME to point at the Container Apps FQDN.

Total time: ~90 minutes, and most of that was waiting for Redis to provision. The actual migration work was about 30 minutes of CLI commands.

Migrate today, build intelligent apps tomorrow

This is where the story goes somewhere Heroku never could — and it's the reason this isn't just a migration, it's an upgrade.

Once your app is on Container Apps, you're already on a platform built for AI-native workloads. No second migration required:

  • Serverless GPU — attach GPU compute to your Container Apps for inference workloads. Run models alongside your app, same environment, same deployment pipeline. No separate ML infrastructure to manage.
  • Dynamic Sessions — spin up isolated, sandboxed code execution environments on demand. Build AI agents that execute tools, run LLM-generated code safely, or offer interactive coding experiences — all within your existing Container Apps environment.
  • AI Foundry — one place to access models from both OpenAI and Anthropic, manage prompts, evaluate outputs, and deploy endpoints. Your app runs on Container Apps; your intelligence runs on Foundry.

The applications being migrated today won't look the same in two years. Choosing a platform that grows with you — from web app to intelligent service — means you won't be shopping for a new home when the business asks for AI features.

 

You don't have to figure this out alone

We've built the resources to make this migration fast and repeatable:

  • Official Migration Guide — End-to-end walkthrough covering assessment, containerization, service mapping, and deployment. Start here.
  • Agent-Assisted Migration Repo — An open-source repository designed to work with GitHub Copilot and other AI coding assistants. It includes an `AGENTS.md` file and six migration skills that walk you through the entire process — from Heroku assessment to DNS cutover — with real CLI commands, Dockerfile templates for five languages, Bicep IaC, and GitHub Actions workflows.

Point Copilot at the repo alongside your app's source code, and it becomes a migration pair-programmer: running the right commands, generating Dockerfiles, setting up CI/CD, and flagging things you might miss. This isn't a magic migrate my app button. It's more like having a colleague who has done this migration twenty times sitting next to you while you do it.

 

The cost math works

Let's talk numbers.

Heroku plan
Monthly cost
Container Apps equivalent
Monthly cost
Standard-1X (idle most of the day)$25/moConsumption plan (scale to zero)~$0–5/mo
Performance-L (steady traffic)$500/moDedicated plan with autoscalingMeaningfully less
10 low-traffic apps across dev/staging/prod$250+/moConsumption plan with free grantsNear zero

Container Apps' monthly free grant covers 180,000 vCPU-seconds and 2 million requests. For apps that idle most of the day, that's often enough to pay nothing at all. The biggest savings come from workloads that don't run 24/7. Heroku charges for every hour a dyno is running, period. Container Apps charges for actual compute consumption and scales to zero when there's no traffic.

 

Heroku taught a generation of developers that shipping should feel like magic. That lesson isn't going anywhere — we're building on it. Azure Container Apps carries the same developer-first philosophy forward, on a platform that's still writing new chapters.

Updated Mar 19, 2026
Version 1.0
No CommentsBe the first to comment