Migrer de Heroku vers Laravel Cloud, ce n’est pas “changer d’hébergeur”. C’est déplacer un ensemble de contrats implicites (build, runtime, réseau, logs, backups, cron, add-ons) vers une nouvelle plateforme — sans casser ton produit, ni ton sommeil.
Le vrai bon plan, ce n’est pas de courir après un “-30%”. Le bon plan, c’est de basculer avec une checklist et une estimation chiffrée qui prend en compte les coûts… et les risques.
Ce que le case study raconte vraiment (au-delà du “-30%”)
Le cas d’école est intéressant pour une raison simple : il cumule des contraintes réalistes. Plusieurs applications, une base de données déjà lourde (dizaines de Go), et des exigences sécurité/secteur strictes. Le message utile n’est pas “Laravel Cloud est moins cher”, c’est plutôt :
- La migration se gagne sur la préparation (inventaire, dépendances, chemins critiques).
- Le coût infra n’est qu’une ligne : l’observabilité, les backups, la bande passante, le temps humain et le risque de rollback comptent tout autant.
- Le “mois 1” est trompeur : tu peux économiser vite, mais tu peux aussi découvrir après coup un coût caché (egress, logs, workers, storage).
Sponsorisé par Le Scribouillard
Besoin de contenu optimisé SEO ?
Utilisez la meilleure plateforme française de création de contenu assistée par IA ! Et générez des articles pour moins de 1€ !
Avant de toucher à l’infra : l’audit express (à faire en 60–90 min)
Si tu veux une migration “propre”, tu commences par une cartographie. Tu veux une feuille A4 (ou un doc) avec :
- Apps concernées : repo, branche, version PHP/Laravel, dépendances natives (extensions, libs système).
- Dynos Heroku actuels : web, worker, scheduler, taille, autoscaling, heures de fonctionnement.
- Base de données : moteur, taille, nombre de connexions, extensions, jobs lourds (migrations, rapports, ETL).
- Queues : driver (Redis/SQS/DB), nombre de workers, volumétrie (jobs/min), jobs critiques.
- Cache / sessions : Redis ? TTL ? dépendance à la persistance ?
- Stockage : S3-like ? local ? génération de fichiers ? traitements médias ?
- Cron / scheduler : fréquence, tâches sensibles (facturation, relances, imports).
- Sortants : email, webhooks, APIs tierces, IP allowlists.
- Observabilité : logs drains, APM, métriques, alertes, rotation/rétention.
- RTO/RPO (même approximatifs) : combien de temps de panne acceptable, combien de perte de données tolérable.
Ce document est ta vérité pendant la migration. Sans lui, tu migres “au feeling” — et tu le payes.
Checklist migration Laravel : ce qui casse en vrai
1) Build & runtime : reproduire l’environnement, pas “ça compile chez moi”
- Verrouille ta version de PHP et tes extensions nécessaires (imagick, intl, gd, etc.).
- Vérifie ton process d’assets (Vite, build prod, cache busting) et où sont servis les fichiers.
- Assure-toi que les dossiers write sont corrects (storage, cache) et que les permissions ne changent pas “en prod”.
- Si tu avais des comportements liés à Heroku (ephemeral filesystem, release phase, etc.), note-les explicitement.
2) Variables d’environnement & secrets : ton futur incident #1
- Export complet des Config Vars Heroku (sans en oublier : services tiers, webhooks, clés de chiffrement, salts, etc.).
- Vérifie que APP_KEY ne change pas (sinon sessions/chiffrements cassent).
- Évite de “recopier à la main” : fais une liste contrôlée, relue, avec propriétaire et date.
- Décide où vivent les secrets (gestionnaire intégré, vault, etc.) et qui y a accès.
3) Base PostgreSQL : le sujet sérieux (downtime, extensions, connexions)
- Plan de transfert : dump/restore, réplication logique, ou fenêtre de maintenance. Choisis, et écris-le.
- Extensions : liste ce que tu utilises (ex: citext, pg_trgm, uuid-ossp). Tu veux vérifier que la cible supporte pareil.
- Connexions : sur une nouvelle infra, le pool/limite peut changer. Anticipe (ex: PgBouncer ou équivalent selon ta stack).
- Backups : fréquence, rétention, test de restore (au moins une fois, sinon c’est une croyance).
- Migrations : si tu as des migrations longues, prévois un plan (index concurrent, découpage, etc.).
4) Cache & sessions : cohérence et persistance
- Confirme ton driver (Redis, database…).
- Si tu relies la session à Redis, valide les TTL, et le comportement en cas de purge.
- Teste explicitement : login, refresh token, “remember me”, CSRF, file uploads.
5) Queues & workers : le sujet qui se voit… 3 heures après la bascule
- Fais une liste des queues (noms, priorités) et des workers (nombre, concurrence).
- Identifie les jobs “à effet de bord” (paiement, email, synchronisation) et ajoute de l’idempotence si ce n’est pas déjà le cas.
- Valide les timeouts, retries, backoff, et la visibilité des échecs (failed jobs, alertes).
- Prévois le plan “file d’attente gelée” pendant la migration si nécessaire.
6) Scheduler (cron) : le piège silencieux
- Liste tous les
schedule()et leurs impacts. - Décide comment le scheduler tourne sur la nouvelle plateforme (un seul leader, éviter le double-run).
- Surveille les tâches longues : elles doivent être queue-ifiées si possible (sinon tu bloques ton tick).
7) Storage & assets : ne confonds pas “disque” et “stockage”
- Si tu utilisais le filesystem local sur Heroku : rappelle-toi que c’est éphémère. La migration est le moment de faire propre (S3 compatible).
- Vérifie les URLs publiques, les permissions, la stratégie de cache, les transformations (thumbnails, conversions).
- Teste un parcours utilisateur complet : upload → traitement → affichage → suppression.
8) Emails, webhooks, tâches sortantes : compatibilité et réputation
- Valide la config sortante (SMTP/HTTP API) et la gestion des bounces.
- Si tu as des webhooks entrants, anticipe la fenêtre DNS/SSL pour ne pas “perdre” des événements.
- Si tu es en allowlist IP côté client/partenaire : récupère les IP de sortie attendues (ou mets en place une approche qui ne dépend pas d’une IP fixe).
Réseau, DNS, TLS : la checklist “jour J”
- DNS : baisse le TTL 24–48h avant la bascule (sans l’oublier après).
- TLS : certificats, renouvellement, redirections HTTP→HTTPS, HSTS si tu l’utilises.
- Domaines : tous les sous-domaines (app, api, admin, assets) et leurs routes.
- CDN (si tu en as un) : invalidation, headers cache-control, compression, images.
- CORS : origines autorisées, préflight, endpoints sensibles.
Observabilité & ops : sinon tu ne sais pas si c’est “cassé” ou juste “lent”
Ton objectif : avoir, dès la première minute, de quoi diagnostiquer un bug sans SSH-panique.
- Logs applicatifs : format, centralisation, corrélation request-id si possible.
- Erreurs : Sentry (ou équivalent) branché, environnements séparés, release tags.
- APM : latence, throughput, erreurs, endpoints critiques, jobs de queue.
- Métriques DB : CPU, I/O, connexions, locks, slow queries.
- Alerting : au minimum erreurs 5xx, saturation DB, queue en backlog, job failure rate.
Plan de bascule sans sueur froide (le runbook minimal)
Tu veux un plan écrit, avec un ordre. Exemple de séquence (à adapter) :
- J-2 : environnement de staging sur Laravel Cloud, smoke tests, charge légère, validation des intégrations.
- J-1 : backups vérifiés, TTL DNS abaissé, runbook relu, responsabilité claire (qui fait quoi).
- Jour J : fenêtre de maintenance si nécessaire, gel des writes (ou stratégie de rattrapage), migration DB, déploiement, warm-up, bascule DNS, surveillance renforcée.
- J+1 : post-mortem à chaud (même si tout va bien), et plan d’amélioration.
# Runbook très simple (à adapter à ton contexte)
php artisan down --render="errors::maintenance"
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan upImportant : le “runbook” ne sert pas à faire joli. Il sert à réduire les décisions sous stress.
Estimer le gain : une méthode simple (coûts + risques)
Tu veux une estimation utile avant migration, pas une promesse marketing. La méthode pragmatique :
Étape 1 — Ton coût Heroku réel (pas juste le prix des dynos)
- Compute : dynos web + dynos worker + autoscaling.
- DB : plan Postgres + stockage + backups + followers si tu en as.
- Redis : plan + options (persistence, HA).
- Add-ons : logs, APM, email, monitoring, etc.
- Bande passante / egress : souvent sous-estimée.
- Coût humain : le temps “ops” mensuel (incidents, lenteurs, tuning).
Étape 2 — Le coût cible (Laravel Cloud) par briques
- Web : combien d’instances, quelle taille, quel headroom ?
- Workers : sépare ton besoin “moyen” et ton besoin “pics”.
- DB : taille + IOPS + backups + stratégie d’évolution.
- Cache/Queue : Redis ou équivalent, et sa criticité.
- Storage : volume + requêtes + egress (si tu sers des fichiers).
- Observabilité : logs, traces, rétention.
Étape 3 — Ajoute le coût de migration (et arrête de te mentir)
Une estimation qui oublie la migration n’est pas une estimation, c’est un pitch.
- Temps dev/ops : audit, staging, scripts, tests, runbook, cutover.
- Coût risque : un buffer (même petit) pour absorber un incident post-bascule.
- Double run : 1 à 2 semaines de chevauchement de facturation (souvent nécessaire).
Un modèle de comparaison qui marche (simple table)
| Poste | Heroku / mois | Laravel Cloud / mois | Notes |
|---|---|---|---|
| Compute (web) | €… | €… | Instances, autoscaling, headroom |
| Compute (workers) | €… | €… | Backlog toléré, pics |
| PostgreSQL | €… | €… | Stockage, backups, I/O |
| Redis / cache / queue | €… | €… | Périmètre (sessions, queues) |
| Logs / APM | €… | €… | Rétention, alerting |
| Storage + egress | €… | €… | Le poste “surprise” classique |
| Total récurrent | €… | €… | |
| Migration (one-shot) | €… | Temps + chevauchement + buffer | |
Ensuite, tu calcules un payback simple :
- Gain mensuel = Total Heroku − Total Laravel Cloud
- Payback (mois) = Coût migration one-shot ÷ Gain mensuel
Si le payback est > 6–9 mois pour une petite app, pose-toi la question. Si tu es à 1–3 mois, ça devient une décision évidente (à condition que le risque opérationnel soit maîtrisé).
Les pièges classiques (ceux qui font perdre une journée)
- Oublier un worker : la prod “marche”, mais rien ne se traite en arrière-plan.
- Double scheduler : deux instances qui lancent la même tâche = emails doublés, facturation doublée, chaos.
- Connexions DB : trop de connexions ouvertes → saturation, timeouts, et tout le monde accuse “le nouvel hébergeur”.
- Storage mal pensé : liens cassés, headers cache foireux, ou egress qui explose.
- Observabilité branchée après : tu te prives de diagnostic au moment où tu en as le plus besoin.
- Rollback flou : si tu ne sais pas revenir en arrière, tu n’as pas un plan, tu as un vœu.
Mon avis (tranché) : la migration réussie, c’est une migration ennuyeuse
Si tout est bien préparé, la bascule est presque anticlimatique. C’est ça le but : une migration “plate”, monitorée, avec des checklists, un runbook, et des chiffres qui tiennent debout.
Le “-30%” est un bonus. La vraie victoire, c’est de reprendre le contrôle : coûts lisibles, infra cohérente avec Laravel, et une prod qui ne dépend pas de rituels.