Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Assess and migrate workloads from AWS, GCP, or other clouds to Azure services.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/services/app-service/heroku-to-app-service.md
1# Heroku to Azure App Service Migration23Detailed guidance for migrating Heroku applications to Azure App Service.45## Service Mapping67| Heroku Service | Azure Equivalent |8|---------------|------------------|9| Heroku App | Azure App Service |10| Dynos (Web) | App Service instances |11| Dynos (Worker) | WebJobs (continuous) or Azure Functions |12| Procfile | Startup command / Docker entrypoint |13| Buildpacks | Docker or App Service runtime stacks |14| Config Vars | App Settings / App Configuration / Key Vault |15| Heroku Postgres | Azure Database for PostgreSQL Flexible Server |16| Heroku Redis | Azure Cache for Redis |17| Heroku Kafka | Azure Event Hubs (Kafka-compatible) |18| Add-ons (general) | Azure managed services |19| Heroku Pipelines | GitHub Actions / Azure DevOps |20| Review Apps | Deployment Slots |21| Heroku CI | GitHub Actions |22| Heroku Scheduler | WebJobs (triggered) or Azure Functions Timer |23| Heroku ACM (SSL) | App Service Managed Certificate |24| Custom Domains | App Service Custom Domains |25| Heroku Logs / Logplex | Application Insights / Azure Monitor |26| Heroku Metrics | Azure Monitor Metrics |27| Heroku Connect | Azure Data Factory or Logic Apps |28| Private Spaces | App Service Environment (ASE) |2930## Dyno → App Service Plan Mapping3132| Heroku Dyno Type | App Service Plan | Notes |33|-------------------|------------------|-------|34| Free / Eco | Free (F1) | Dev/test only — F1 has shared compute with quota limits (CPU minutes), not equivalent to Heroku's 60 min/day cap. See [App Service Free SKU limits](https://learn.microsoft.com/azure/app-service/overview-hosting-plans#how-much-do-i-pay-for-the-free-and-shared-tiers) |35| Basic | Basic (B1) | No auto-scale, no slots |36| Standard-1X (512 MB) | Standard (S1) | Auto-scale, slots, custom domains |37| Standard-2X (1 GB) | Standard (S2) | More memory |38| Performance-M (2.5 GB) | Premium v3 (P1v3) | VNet, more instances |39| Performance-L (14 GB) | Premium v3 (P3v3) | High-memory workloads |40| Private-M / Private-L | App Service Environment (ASE) | Network-isolated |4142## Procfile → Startup Configuration4344### Web Process4546| Procfile Entry | Azure Equivalent |47|---------------|------------------|48| `web: node server.js` | Startup command: `node server.js` |49| `web: gunicorn app:app` | Startup command: `gunicorn --bind=0.0.0.0 --timeout 600 app:app` |50| `web: java -jar target/app.jar` | Startup command: `java -jar app.jar` |51| `web: bundle exec puma -C config/puma.rb` | Custom container with Dockerfile |5253### Worker Process5455Heroku worker dynos have no direct App Service equivalent. Migration paths:5657| Heroku Worker Pattern | Azure Equivalent |58|----------------------|------------------|59| `worker: node worker.js` | WebJob (continuous) |60| `worker: celery -A tasks worker` | Container App or AKS |61| `clock: node scheduler.js` | Azure Functions Timer trigger |62| `release: rake db:migrate` | Deployment slot swap scripts |6364## Add-ons → Azure Managed Services6566| Heroku Add-on | Azure Equivalent | Migration Notes |67|--------------|------------------|-----------------|68| Heroku Postgres | PostgreSQL Flexible Server | Use Azure DMS for data migration |69| Heroku Redis | Azure Cache for Redis | Export/import RDB or use replication |70| Heroku Kafka | Azure Event Hubs (Kafka API) | Compatible Kafka protocol |71| Papertrail | Application Insights | Structured logging migration |72| New Relic | Application Insights | APM feature parity |73| SendGrid | Azure Communication Services or SendGrid on Azure | SendGrid available via Azure Marketplace |74| Cloudinary | Azure Blob Storage + CDN | Media storage + delivery |75| Memcachier | Azure Cache for Redis | Redis supports memcache patterns |76| Bonsai (Elasticsearch) | Azure AI Search or Elastic on Azure | Search service migration |77| Heroku Scheduler | Azure Functions Timer trigger | Cron-based scheduling |78| Bucketeer (S3) | Azure Blob Storage | Object storage migration |7980## Config Vars → App Configuration / Key Vault8182| Config Var Type | Azure Target | Implementation |83|----------------|--------------|----------------|84| `DATABASE_URL` | App Setting (managed identity) | Use Entra auth, not connection string |85| `REDIS_URL` | App Setting | Azure Cache connection string or managed identity |86| `SECRET_KEY` | Key Vault reference | `@Microsoft.KeyVault(SecretUri=...)` |87| `API_KEY` (third-party) | Key Vault reference | Store in Key Vault |88| `NODE_ENV` / `RAILS_ENV` | App Setting | Add as a regular App Setting (e.g., `NODE_ENV=production`) — controls runtime behavior. Do NOT confuse with `WEBSITES_NODE_DEFAULT_VERSION`, which controls the Node.js engine version on Windows App Service. |89| `PORT` | Auto-injected | App Service sets `PORT` automatically |90| Feature flags | App Configuration | Feature management support built-in |9192> ⚠️ **Warning:** Heroku's `DATABASE_URL` includes credentials. On Azure, use managed identity authentication instead. Never migrate connection strings with embedded passwords.9394## Buildpacks → Docker9596For apps using standard runtimes, use App Service runtime stacks directly. For custom buildpacks, migrate to Docker:9798| Buildpack Scenario | Azure Approach |99|-------------------|----------------|100| Official Node.js buildpack | App Service Node.js runtime stack |101| Official Python buildpack | App Service Python runtime stack |102| Official Java buildpack | App Service Java runtime stack |103| Multi-buildpack (e.g., Node + Python) | Custom Dockerfile |104| Custom buildpack (apt packages) | Custom Dockerfile |105| Heroku CNB (Cloud Native Buildpack) | Azure Container Apps with CNB |106107## Heroku Pipelines → GitHub Actions108109| Pipeline Feature | Azure Equivalent |110|-----------------|------------------|111| Pipeline stages (dev → staging → prod) | GitHub Actions environments |112| Auto-deploy on push | GitHub Actions `on: push` trigger |113| Review Apps | Deployment slots with PR-based deploy |114| Pipeline promotion | Slot swap (staging → production) |115| Heroku CI test runner | GitHub Actions test job |116| Release phase | Pre-swap slot scripts |117118### Example: GitHub Actions Deployment119120```yaml121name: Deploy to App Service122on:123push:124branches: [main]125jobs:126deploy:127runs-on: ubuntu-latest128permissions:129id-token: write # Required for azure/login@v2 OIDC token request130contents: read # Required to checkout the repo131steps:132- uses: actions/checkout@v4133- uses: azure/login@v2134with:135client-id: ${{ secrets.AZURE_CLIENT_ID }}136tenant-id: ${{ secrets.AZURE_TENANT_ID }}137subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}138- uses: azure/webapps-deploy@v3139with:140app-name: '<app-name>'141slot-name: 'staging'142```143144> ⚠️ Without the `permissions:` block, `azure/login@v2`'s OIDC token request fails with HTTP 403.145146## Review Apps → Deployment Slots147148| Heroku Review Apps | App Service Deployment Slots |149|-------------------|------------------------------|150| Auto-create per PR | Create via GitHub Actions per PR |151| Unique URL per PR | `<app>-<slot>.azurewebsites.net` |152| Auto-destroy on PR close | Delete slot in PR close workflow |153| Shared pipeline config | Slot-specific App Settings |154| `app.json` postdeploy scripts | Slot swap pre/post actions |155156## Reference Links157158- [Heroku to Azure migration guide](https://learn.microsoft.com/en-us/azure/app-service/overview)159- [App Service deployment slots](https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots)160- [GitHub Actions for App Service](https://learn.microsoft.com/en-us/azure/app-service/deploy-github-actions)161- [App Service managed identity](https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity)162