Cloud
18 min de lecture

Migration Heroku vers AWS : Comment Réduire vos Coûts de 50 à 90%

Guide complet de migration Heroku vers AWS avec cas réel Monnier : 53% d'économies immédiates (557€→259€/mois), Elastic Beanstalk, Spot Instances et optimisations.

Arthur Zinck
Arthur Zinck
Expert DevOps Kubernetes & Cloud

Migration Heroku vers AWS : Comment Réduire vos Coûts de 30 à 70%

La migration de Heroku vers AWS est devenue incontournable pour les entreprises en croissance. Heroku, bien que pratique pour prototyper rapidement, devient rapidement très coûteux à l’échelle. Cette migration peut générer entre 30% et 70% d’économies tout en offrant plus de contrôle et de flexibilité.

Cet article détaille le processus complet de migration basé sur un cas réel : Monnier, plateforme e-commerce qui a réduit ses coûts infrastructure de 72% en migrant vers AWS Elastic Beanstalk.

Pourquoi Migrer de Heroku vers AWS ?

Le Coût Croissant de Heroku

Heroku fonctionne avec une tarification par “dyno” (conteneur applicatif) qui devient rapidement prohibitive :

Exemple réel Monnier :

Heroku : - 1x Basic dyno (Front) : 7€/mois - 1x Standard-2X dyno (Strapi Front) : 50€/mois - 2x Performance-M dynos (Workers) : 500€/mois - Total : 557€/mois

AWS Elastic Beanstalk (architecture réelle déployée) : - t3.medium (Front) : 33.93€/mois - c5.large (Strapi) : 71.42€/mois - c5.large (Worker) : 142.85€/mois - t3.medium Spot (Traitement photos) : 11.31€/mois - Total : 259.51€/mois

Économie réelle : -53.4% (297€ économisés/mois, soit 3 570€/an)

Et avec un dimensionnement optimal + Savings Plans : jusqu’à -89.8% d’économies possibles.

Les Limites Techniques de Heroku

Au-delà du coût, Heroku impose des contraintes :

  • Scaling limité : Impossible de scaler certains composants indépendamment
  • Vendor lock-in : Dépendance aux add-ons propriétaires Heroku
  • Visibilité réduite : Métriques et logs limités sans add-ons coûteux
  • Performance : Réseau partagé entre tenants, latence variable
  • Personnalisation : Architecture figée, impossible d’optimiser finement

Cas Réel : Migration Monnier (E-commerce)

Contexte du Projet

Entreprise : Monnier, plateforme e-commerce mode Infrastructure Heroku : Architecture multi-services avec dynos Performance Objectif : Réduire drastiquement les coûts tout en améliorant les performances

Architecture Avant Migration

Stack Heroku : - 1x Basic dyno (Front Nuxt - 1 CPU, 0.5GB RAM) : 7€/mois - 1x Standard-2X dyno (Strapi Front - 2 CPU, 1GB RAM) : 50€/mois - 1x Performance-M dyno (Strapi Worker - 12 CPU, 2.5GB RAM) : 250€/mois - 1x Performance-M dyno (Traitement photos - 12 CPU, 2.5GB RAM) : 250€/mois - PostgreSQL déjà hébergé sur AWS RDS - Redis Premium-2

Coût mensuel Heroku : 557€/mois (6 684€/an)

Stratégie de Migration

Phase 1 : Analyse et Dimensionnement

Audit de l’existant :

# Analyse des métriques Heroku
heroku ps --app monnier-prod
heroku redis:info --app monnier-prod

Questions clés : - Quelles sont les ressources réellement consommées (CPU, RAM, I/O) ? - Quels pics de charge l’application subit-elle ? - Quelles dépendances aux add-ons Heroku spécifiques ? - Quelle partie du code dépend de la plateforme Heroku ?

Résultat Monnier : - Sur-provisionnement massif détecté : Performance-M (12 CPU, 2.5GB RAM) alors que t3.medium (2 CPU, 4GB RAM) suffit largement - CPU réel : 20-30% des capacités Heroku sur les dynos Performance-M - PostgreSQL : Déjà sur AWS RDS (aucune migration nécessaire) - Redis : Cache applicatif - Front Nuxt : Basic dyno largement sur-dimensionné pour un front statique

Phase 2 : Choix de la Stack AWS

Plusieurs options pour migrer depuis Heroku :

Option 1 : AWS Elastic Beanstalk (choisi par Monnier) - ✅ Service managé similaire à Heroku - ✅ Transition en douceur pour les équipes - ✅ Load balancing et auto-scaling intégrés - ✅ Déploiement simple via CLI ou CI/CD - ⚠️ Moins flexible que Kubernetes

Option 2 : Amazon ECS/Fargate - ✅ Conteneurisation complète - ✅ Scaling granulaire - ✅ Intégration parfaite avec l’écosystème AWS - ⚠️ Plus complexe à configurer

Option 3 : Amazon EKS (Kubernetes) - ✅ Maximum de flexibilité et portabilité - ✅ GitOps avec ArgoCD possible - ✅ Multi-cloud ready - ⚠️ Complexité opérationnelle élevée - ⚠️ Overhead de gestion du cluster

Pourquoi Elastic Beanstalk pour Monnier ? - Équipe dev habituée à Heroku, transition progressive souhaitée - Pas besoin de la complexité Kubernetes à court terme - Time-to-market prioritaire - Service managé AWS réduit la charge opérationnelle

Phase 3 : Migration de l’Infrastructure

1. Configuration Base de Données (Déjà sur AWS RDS)

Dans le cas de Monnier, PostgreSQL était déjà hébergé sur AWS RDS, ce qui simplifie considérablement la migration. Seule action nécessaire : ajuster les security groups.

# Ajouter règle security group pour Elastic Beanstalk
aws ec2 authorize-security-group-ingress \
  --group-id sg-xxxxx-rds \
  --protocol tcp \
  --port 5432 \
  --source-group sg-yyyyy-beanstalk

Avantage majeur : Pas de migration de données, pas de downtime PostgreSQL, connexion directe depuis les nouvelles instances Elastic Beanstalk.

Si votre base était sur Heroku Postgres, voici le process complet :

Migration PostgreSQL Heroku → AWS RDS

# Export depuis Heroku Postgres
heroku pg:backups:capture --app monnier-prod
heroku pg:backups:download --app monnier-prod

# Créer instance RDS
aws rds create-db-instance \
  --db-instance-identifier monnier-prod \
  --db-instance-class db.m5.large \
  --engine postgres \
  --engine-version 15.4 \
  --allocated-storage 100 \
  --storage-encrypted \
  --backup-retention-period 7 \
  --multi-az

# Restauration
pg_restore -h monnier-prod.xxxx.rds.amazonaws.com \
  -U postgres -d monnier latest.dump

Points d’attention : - Choisir la même version PostgreSQL - Activer Multi-AZ pour haute disponibilité - Tester les performances en charge avant cutover

2. Migration Redis

# ElastiCache Redis cluster
aws elasticache create-cache-cluster \
  --cache-cluster-id monnier-redis \
  --cache-node-type cache.m5.large \
  --engine redis \
  --num-cache-nodes 1 \
  --engine-version 7.0

# Export/Import des données si nécessaire
redis-cli --rdb /tmp/dump.rdb

3. Configuration Elastic Beanstalk

Création de l’application :

eb init monnier-api --platform "Node.js 18" --region eu-west-1
eb create monnier-prod \
  --instance-type m5.large \
  --scale 3 \
  --envvars DATABASE_URL=$DB_URL,REDIS_URL=$REDIS_URL

Configuration auto-scaling :

# .ebextensions/autoscaling.config
option_settings:
  aws:autoscaling:asg:
    MinSize: 3
    MaxSize: 12
  aws:autoscaling:trigger:
    MeasureName: CPUUtilization
    Statistic: Average
    Unit: Percent
    UpperThreshold: 70
    LowerThreshold: 30

4. Adaptation du Code Applicatif

Variables d’environnement :

// Avant (Heroku)
const dbUrl = process.env.DATABASE_URL; // Format Heroku spécifique

// Après (AWS compatible)
const dbConfig = {
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  ssl: { rejectUnauthorized: false }
};

Logs :

// Avant : logs Heroku automatiques
console.log('Request processed');

// Après : CloudWatch Logs
const winston = require('winston');
const logger = winston.createLogger({
  transports: [
    new winston.transports.Console(),
    new winston.transports.File({ filename: '/var/log/app.log' })
  ]
});

Phase 4 : Pipeline CI/CD

GitLab CI pour déploiement Elastic Beanstalk :

# .gitlab-ci.yml
stages:
  - build
  - deploy

build:
  stage: build
  script:
    - npm ci
    - npm run build
    - zip -r application.zip . -x "*.git*"
  artifacts:
    paths:
      - application.zip

deploy_production:
  stage: deploy
  only:
    - main
  script:
    # Upload vers S3
    - aws s3 cp application.zip s3://monnier-deployments/app-${CI_COMMIT_SHA}.zip

    # Créer nouvelle version Elastic Beanstalk
    - |
      aws elasticbeanstalk create-application-version \
        --application-name monnier-api \
        --version-label ${CI_COMMIT_SHA} \
        --source-bundle S3Bucket=monnier-deployments,S3Key=app-${CI_COMMIT_SHA}.zip

    # Déployer
    - |
      aws elasticbeanstalk update-environment \
        --environment-name monnier-prod \
        --version-label ${CI_COMMIT_SHA}

Rollback facile :

# Lister les versions
aws elasticbeanstalk describe-application-versions \
  --application-name monnier-api

# Rollback vers version précédente
aws elasticbeanstalk update-environment \
  --environment-name monnier-prod \
  --version-label <version-precedente>

Phase 5 : Migration Progressive (Blue-Green)

Stratégie de cutover sans downtime :

  1. Infrastructure en parallèle :

    • Heroku continue de tourner
    • AWS Elastic Beanstalk configuré et testé
    • Bases de données synchronisées (réplication)
  2. Tests de charge :

    # Simulation charge avec k6
    k6 run --vus 100 --duration 30m load-test.js
    
    1. Migration DNS progressive :

      # Route 53 weighted routing
      aws route53 change-resource-record-sets \
      --hosted-zone-id Z123456 \
      --change-batch '{
      "Changes": [{
      "Action": "CREATE",
      "ResourceRecordSet": {
      "Name": "api.monnier.com",
      "Type": "A",
      "SetIdentifier": "AWS",
      "Weight": 10,
      "AliasTarget": {
        "HostedZoneId": "Z123",
        "DNSName": "monnier-prod.elasticbeanstalk.com"
      }
      }
      }]
      }'
      
  3. Bascule progressive :

    • Jour 1 : 10% trafic AWS, 90% Heroku
    • Jour 3 : 50% AWS, 50% Heroku
    • Jour 5 : 100% AWS
  4. Surveillance étroite :

    # CloudWatch metrics
    aws cloudwatch get-metric-statistics \
    --namespace AWS/ElasticBeanstalk \
    --metric-name CPUUtilization \
    --dimensions Name=EnvironmentName,Value=monnier-prod \
    --start-time 2025-01-01T00:00:00Z \
    --end-time 2025-01-02T00:00:00Z \
    --period 300 \
    --statistics Average
    

    Phase 6 : Optimisation Post-Migration

    Une fois la migration validée, optimisations pour réduire encore les coûts :

    Right-Sizing

    Analyse des métriques : - CPU moyen : 35% → instance sur-dimensionnée - RAM : 60% utilisée → marge correcte - I/O disque : faible → EBS gp3 suffit (vs io2) Ajustements :

    # Passer de m5.large à m5.medium pour certains workers
    eb scale 3 --instance-type m5.medium monnier-workers
    

Résultat Monnier : 15% d’économies supplémentaires via right-sizing.

Spot Instances pour Workers Non-Critiques

# .ebextensions/spot-instances.config
option_settings:
  aws:ec2:instances:
    SpotFleetOnDemandBase: 1
    SpotFleetOnDemandAboveBasePercentage: 0
    SpotMaxPrice: 0.05

Économies : 60-70% sur les workers batch/background.

Reserved Instances / Savings Plans

Pour les instances stables :

# Achat Reserved Instance 1 an
aws ec2 purchase-reserved-instances-offering \
  --reserved-instances-offering-id xxxxx \
  --instance-count 3

Économies : 30-40% sur instances on-demand.

Optimisation Base de Données

RDS Performance Insights :

aws rds describe-db-instances \
  --db-instance-identifier monnier-prod \
  --query 'DBInstances[0].PerformanceInsightsEnabled'

Actions : - Identifier les requêtes lentes (>100ms) - Ajouter indexes manquants - Optimiser les requêtes N+1

Résultat : Possibilité de downgrade RDS de db.m5.large → db.m5.medium.

Résultats Monnier

Économies Réalisées

Coûts mensuels détaillés :

Service Instance Heroku Coût Heroku Instance AWS proposée Coût AWS (on-demand) Coût AWS (Savings Plans) Instance réelle Coût réel
Front Nuxt Basic (1 CPU, 0.5GB) 7€ t3.nano (2 CPU, 0.5GB) 4.39€ 2.70€ t3.medium 33.93€
Strapi Front Standard-2X (2 CPU, 1GB) 50€ t3.small (2 CPU, 2GB) 17.56€ 10.80€ c5.large 71.42€
Strapi Worker Performance-M (12 CPU, 2.5GB) 250€ t3.medium (2 CPU, 4GB) 35.12€ 21.70€ c5.large 142.85€
Traitement photos Performance-M (12 CPU, 2.5GB) 250€ t3.medium (2 CPU, 4GB) 35.12€ 21.70€ t3.medium Spot 11.31€
Base de données RDS (déjà AWS)
TOTAL 557€ 92.19€ 56.90€ 259.51€
TOTAL ANNUEL 6 684€ 1 106€ 682.80€ 3 114€

Résultats : - Économie avec dimensionnement optimal : 557€ → 56.90€/mois = -89.8% (500€ économisés/mois) - Infrastructure réelle déployée : 557€ → 259.51€/mois = -53.4% (297€ économisés/mois) - Économie annuelle réelle : 3 570€

Note importante : L’infrastructure réelle utilise des instances plus puissantes (t3.medium au lieu de t3.nano pour le front, c5.large au lieu de t3.small/medium) pour garantir de la marge. Malgré ce sur-provisionnement AWS, l’économie reste de 53% par rapport à Heroku.

Optimisation maximale possible : En appliquant le dimensionnement optimal + Savings Plans, l’économie atteindrait 89.8% (de 557€ à 56.90€/mois).

Détail de l’Optimisation Spot Instances

Traitement photos : Worker non-critique migré vers t3.medium Spot : - Coût on-demand : 35.12€/mois - Coût Spot : 11.31€/mois - Économie : -67.8% sur ce composant

Les Spot Instances sont parfaites pour les workloads tolérants aux interruptions (traitement batch, workers non temps-réel).

Améliorations Techniques

Performance : - Temps de réponse : comparable voire meilleur (même région AWS pour compute + RDS) - Déploiements : automatisés via GitLab CI vers S3 + Elastic Beanstalk - Rollback : instantané (versions Elastic Beanstalk)

Contrôle : - Visibilité complète : CloudWatch métriques détaillées par instance - Logs centralisés : CloudWatch Logs Insights - Sécurité : VPC privé, security groups granulaires entre services

Flexibilité : - Spot Instances pour worker traitement photos : -67.8% sur ce composant - Scaling indépendant par service - Possibilité d’optimiser encore (Savings Plans : -38% supplémentaires)

Détail du Sur-Provisionnement Heroku Détecté

Traitement photos : - Heroku : Performance-M (12 CPU, 2.5GB RAM) à 250€/mois - AWS optimal : t3.medium (2 CPU, 4GB RAM) à 35.12€/mois - Sur-provisionnement : 6x plus de CPU que nécessaire

Ce sur-dimensionnement est typique sur Heroku : les dynos imposent des paliers fixes (Basic → Standard → Performance) sans granularité, forçant à payer pour des ressources inutilisées.

Checklist Migration Heroku → AWS

Pré-Migration

  • [ ] Audit des ressources Heroku réellement consommées (CPU, RAM, I/O)
  • [ ] Identification des add-ons Heroku et équivalents AWS
  • [ ] Analyse des dépendances code au runtime Heroku
  • [ ] Estimation budget AWS (calculateur AWS Pricing)
  • [ ] Choix de la stack AWS (Beanstalk, ECS, EKS)

Migration Infrastructure

  • [ ] Création VPC AWS avec subnets publics/privés (si nécessaire)
  • [ ] Migration base de données vers RDS (si pas déjà sur AWS)
  • [ ] Ajustement security groups pour connexion RDS ↔ Compute
  • [ ] Migration Redis vers ElastiCache
  • [ ] Configuration Elastic Beanstalk / ECS / EKS
  • [ ] Setup load balancer + auto-scaling
  • [ ] Configuration CloudWatch monitoring

Migration Applicative

  • [ ] Adaptation variables d’environnement
  • [ ] Modification configuration logs (CloudWatch)
  • [ ] Tests de l’application sur AWS (staging)
  • [ ] Configuration secrets (AWS Secrets Manager)
  • [ ] Tests de charge (k6, Locust, JMeter)

CI/CD

  • [ ] Pipeline GitLab/GitHub vers AWS
  • [ ] Déploiement automatisé (S3 + Elastic Beanstalk CLI)
  • [ ] Tests automatisés pré-déploiement
  • [ ] Rollback automatique en cas d’erreur

Cutover

  • [ ] Synchronisation bases de données Heroku → AWS (si applicable)
  • [ ] Vérification connectivité RDS depuis nouvelles instances
  • [ ] Migration DNS progressive (Route 53 weighted routing)
  • [ ] Monitoring étroit pendant 72h
  • [ ] Validation métriques performance
  • [ ] Désactivation Heroku après validation complète

Post-Migration

  • [ ] Right-sizing instances (analyse 2 semaines de métriques)
  • [ ] Activation Spot Instances pour workloads non-critiques
  • [ ] Achat Reserved Instances / Savings Plans
  • [ ] Optimisation requêtes base de données
  • [ ] Configuration alertes CloudWatch

Alternatives à Elastic Beanstalk

Amazon ECS + Fargate

Avantages : - Conteneurisation complète (Docker) - Pas de gestion de serveurs (serverless containers) - Scaling granulaire par service

Inconvénients : - Courbe d’apprentissage plus raide - Configuration initiale plus longue

Quand choisir ? : Application déjà conteneurisée, besoin de scaling fin par microservice.

Amazon EKS (Kubernetes)

Avantages : - Portabilité multi-cloud - Écosystème riche (Helm, ArgoCD, Istio) - GitOps natif avec ArgoCD

Inconvénients : - Complexité opérationnelle élevée - Coût du control plane : 72€/mois - Expertise Kubernetes requise

Quand choisir ? : Architecture microservices (10+ services), équipe DevOps expérimentée, stratégie multi-cloud.

Exemple migration vers EKS :

# Deployment Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
  name: monnier-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: monnier-api
  template:
    metadata:
      labels:
        app: monnier-api
    spec:
      containers:
      - name: api
        image: monnier/api:latest
        resources:
          requests:
            cpu: 500m
            memory: 1Gi
          limits:
            cpu: 1000m
            memory: 2Gi
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: db-credentials
              key: url

Erreurs à Éviter

1. Sous-Estimer la Préparation

Erreur : Migrer sans analyser les métriques Heroku réelles ✅ Solution : Auditer 2-4 semaines de métriques CPU/RAM/I/O avant dimensionnement AWS

2. Big Bang Migration

Erreur : Couper Heroku et basculer 100% sur AWS d’un coup ✅ Solution : Migration progressive (weighted routing DNS), rollback facile

3. Négliger les Tests de Charge

Erreur : Valider uniquement en environnement de dev ✅ Solution : Tests de charge réalistes (k6) simulant trafic production

4. Oublier les Coûts Cachés AWS

Erreur : Calculer uniquement EC2 + RDS ✅ Solution : Inclure data transfer, EBS, snapshots, CloudWatch logs

5. Sur-Dimensionner Dès le Début

Erreur : Prendre des instances larges “au cas où” ✅ Solution : Commencer conservateur, right-size après 2 semaines de métriques

Combien de Temps pour Migrer ?

Timeline réaliste pour une application moyenne :

  • Semaine 1-2 : Audit, analyse, choix architecture AWS
  • Semaine 3-4 : Setup infrastructure AWS (staging)
  • Semaine 5-6 : Adaptation code, tests, CI/CD
  • Semaine 7 : Migration bases de données (si nécessaire), tests de charge
  • Semaine 8 : Cutover progressif, surveillance

Total : 6-8 semaines pour une migration maîtrisée.

Cas Monnier : Migration accélérée grâce à PostgreSQL déjà sur AWS. Seule la partie compute Heroku → Elastic Beanstalk a nécessité migration et tests.

Conclusion

La migration Heroku vers AWS peut générer 50 à 90% d’économies tout en améliorant performances, contrôle et flexibilité. Le cas Monnier démontre 53% d’économies immédiates (557€ → 259€/mois) avec possibilité d’atteindre 90% via optimisations (Savings Plans, right-sizing).

Points clés : 1. Détecter le sur-provisionnement Heroku : Les paliers fixes (Basic, Standard, Performance) forcent à payer pour des ressources inutilisées 2. Analyser avant d’agir : métriques Heroku réelles, pas d’estimations 3. Choisir la bonne stack AWS : Beanstalk (simple), ECS (conteneurs), EKS (microservices) 4. Optimiser intelligemment : Spot Instances pour workloads non-critiques, Savings Plans pour prévisible

Résultat Monnier : - 557€/mois sur Heroku259€/mois sur AWS = -53% avec marge confortable - Optimisation maximale possible : 56.90€/mois = -90%

Votre application coûte >500€/mois sur Heroku ? Une migration AWS bien menée peut réduire cette facture de 50 à 90%.

Le passage à AWS ne se limite pas aux économies : c’est aussi reprendre le contrôle de votre infrastructure, gagner en flexibilité et préparer votre scaling futur sans les contraintes d’un PaaS propriétaire.

Points clés à retenir

  • Migration Heroku vers AWS : économies de 50-90% sur coûts infrastructure
  • Cas Monnier : 53% de réduction immédiate (557€ → 259€/mois) avec Elastic Beanstalk
  • Sur-provisionnement Heroku détecté : Performance-M (12 CPU) alors que 2 CPU suffisent
  • Spot Instances pour traitement photos : -67.8% (35€ → 11€/mois)
  • Optimisation maximale possible : -90% via Savings Plans + right-sizing (557€ → 57€/mois)
aws heroku migration-cloud elastic-beanstalk cost-optimization rds elasticache gitlab-ci e-commerce

Partager cet article

Twitter LinkedIn