# Dev, staging et prod dès le premier jour : pourquoi une équipe de trois ne devrait pas attendre

« On séparera les environnements plus tard, quand on aura des utilisateurs. » Nous avons entendu cette phrase de chaque petite équipe avec laquelle nous avons travaillé, et nous l'avons dite nous-mêmes. Elle sonne comme de la prudence : ne construis pas d'infrastructure dont tu n'as pas encore besoin. C'est en réalité un emprunt, contracté au pire taux possible, et cet article est l'échéancier de remboursement.

Nous avons [écrit le guide pratique](/fr/blog/aws-three-accounts-one-cdk-codebase) pour faire tourner trois comptes AWS depuis une seule base de code CDK. Voici le pourquoi, destiné à l'équipe qui a un compte avec tout dedans et une bonne raison de le garder ainsi encore un trimestre.

## Ce que coûte « plus tard »

Séparer les environnements le premier jour, c'est une journée de travail. Les séparer au sixième mois, c'est une semaine. Les séparer au dix-huitième mois, c'est un mois, plus un risque que vous ne pouvez pas chiffrer. Le coût ne croît pas linéairement ; il croît avec le nombre de choses qui ont accumulé de l'état et des noms.

<div class="article-figure">
<svg viewBox="0 0 900 260" width="100%" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Graphique de l'effort pour séparer les environnements en fonction de l'âge du projet. Le premier jour, c'est environ une journée. Au sixième mois, environ une semaine, parce que la base de données, les secrets et le DNS ont de vraies données et de vrais noms. Au dix-huitième mois, environ un mois, avec une bande de risque ombrée, parce que les données de production doivent être sorties du compte partagé sans interruption et que chaque intégration pointe vers l'ancien compte. Une seconde ligne plate montre le coût de fonctionnement de trois environnements dès le départ : environ 60 dollars par mois.">
<g font-family="Inter,system-ui,sans-serif" font-size="12">
<text x="20" y="24" fill="#f1f3ff" font-size="14" font-weight="700">Effort pour séparer les environnements vs. âge du projet</text>
<line x1="70" y1="220" x2="870" y2="220" stroke="#9aa3c7"/><line x1="70" y1="40" x2="70" y2="220" stroke="#9aa3c7"/>
<text x="70" y="240" text-anchor="middle" fill="#9aa3c7" font-size="10">jour 1</text><text x="370" y="240" text-anchor="middle" fill="#9aa3c7" font-size="10">mois 6</text><text x="770" y="240" text-anchor="middle" fill="#9aa3c7" font-size="10">mois 18</text>
<text x="64" y="216" text-anchor="end" fill="#9aa3c7" font-size="10">1 jour</text><text x="64" y="150" text-anchor="end" fill="#9aa3c7" font-size="10">1 sem.</text><text x="64" y="60" text-anchor="end" fill="#9aa3c7" font-size="10">1 mois</text>
<path d="M70,214 C200,212 300,180 370,150 C500,110 650,80 770,56" fill="none" stroke="#ff6b8a" stroke-width="2.5"/>
<path d="M600,90 C700,70 770,56 800,50 L800,120 C740,110 650,120 600,130 Z" fill="#ff6b8a" opacity="0.12"/>
<text x="700" y="140" text-anchor="middle" fill="#ff6b8a" font-size="10">+ risque : sortir les données de prod d'un compte partagé</text>
<circle cx="70" cy="214" r="5" fill="#4fffb0"/><text x="84" y="206" fill="#4fffb0" font-size="11">3 comptes, 1 map de config, 1 rôle OIDC chacun</text>
<circle cx="370" cy="150" r="5" fill="#ffd166"/><text x="384" y="146" fill="#ffd166" font-size="11">la base, les secrets, le DNS ont des noms et des données</text>
<circle cx="770" cy="56" r="5" fill="#ff6b8a"/><text x="760" y="46" text-anchor="end" fill="#ff6b8a" font-size="11">chaque intégration pointe vers l'ancien compte</text>
<line x1="70" y1="200" x2="870" y2="200" stroke="#4fffb0" stroke-width="1.5" stroke-dasharray="5,4"/><text x="868" y="196" text-anchor="end" fill="#4fffb0" font-size="10">coût de 3 environnements dès le jour 1 : ~60 $ / mois</text>
</g>
</svg>
</div>

Au sixième mois, la base de données a de vraies données et un vrai nom. Les secrets ont été copiés à trois endroits. Le DNS pointe vers des choses. Le portable de quelqu'un a un profil nommé `default` qui déploie dans le seul compte qui existe. Sortir la production de ce compte signifie [importer les ressources avec état dans de nouveaux stacks](/fr/blog/cloudformation-500-resource-limit-split-a-stack), repointer chaque webhook et chaque intégration, renouveler chaque secret partagé, et le faire sans interruption. Nous l'avons fait. C'est un projet avec un runbook, et le runbook a une section de retour arrière, et vous préféreriez ne pas en avoir besoin.

## Les trois choses qui tournent mal dans un seul compte

Nous n'argumentons pas en théorie. Chacune est arrivée à une équipe avec laquelle nous avons travaillé, et l'une d'elles nous est arrivée.

**Des données de test en production, ou des données de production en test.** Avec un seul compte, « la base » est un seul cluster, et la séparation est un nom de schéma ou un préfixe de table. Un script de migration avec le mauvais `search_path`, une commande de seed lancée dans le mauvais shell, une requête d'analyse pointée sur la mauvaise table : chacune est une erreur d'un caractère et chacune s'est produite. Dans des comptes séparés, l'erreur de mauvais compte reste possible, mais elle exige d'assumer un rôle différent, et l'outillage de déploiement peut [refuser de le faire sans un drapeau explicite](/fr/blog/same-tag-deploy-and-the-deploy-script-without-ci).

**Un déploiement qui était destiné au dev.** [Notre incident](/fr/blog/cloudformation-deleted-our-app-runner-services) : un `cdk deploy` depuis un portable, avec le mauvais contexte, a supprimé tous les services App Runner d'un environnement. C'était l'environnement de dev, dans le compte de dev, et les dégâts totaux ont été un après-midi. La même commande, dans une configuration à un seul compte, supprime la production. La frontière de compte n'a pas empêché l'erreur ; elle l'a bornée. C'est toute la valeur.

**Le hotfix « juste cette fois ».** Un seul compte sans staging signifie que le seul endroit pour tester un correctif est la production. Donc le correctif va en production, et il marche, et le suivant aussi, et à la fin le processus de déploiement de l'équipe devient « push sur main et on regarde ». L'habitude n'est pas de la bêtise. C'est la réponse rationnelle au fait de n'avoir nulle part ailleurs où regarder. Donnez aux gens un compte de staging qui coûte 20 $ par mois et ils l'utilisent, parce qu'il est là.

## Ce que « dès le premier jour » veut vraiment dire

L'objection à la séparation précoce est en général l'image d'une landing zone : Control Tower, une organisation avec une douzaine d'OU, des service control policies, un compte de services partagés, une journalisation centralisée, un compte réseau avec Transit Gateway. C'est un mois de travail et c'est la bonne chose pour une entreprise de cinquante ingénieurs. C'est la mauvaise chose pour trois, et ce n'est pas ce que nous proposons.

Le minimum qui capture presque toute la valeur :

| À faire le premier jour | À sauter jusqu'à en avoir besoin |
|---|---|
| Une AWS Organization avec trois comptes membres : dev, staging, prod | Control Tower, accélérateurs de landing zone |
| Une map `config` dans la base de code CDK, indexée par environnement | Des unités organisationnelles au-delà de celle par défaut |
| Un [rôle de déploiement OIDC par compte](/fr/blog/github-oidc-deploy-roles-per-aws-account), restreint par branche | Les service control policies |
| `RemovalPolicy.RETAIN` et la protection contre la suppression en prod | Des comptes de services partagés ou de réseau |
| Une vue de facturation consolidée, taguée par environnement | CloudTrail centralisé dans un compte de sécurité |
| Un script de déploiement qui refuse la prod sans `--env prod --yes` | Le peering VPC entre comptes |

C'est une journée. Le diff CDK pour passer d'un environnement à trois, c'est la map de config et la valeur de contexte `env` ; tout le reste dans le stack est déjà paramétré ou devrait l'être. Et les trois comptes coûtent, à taille minimale avec Aurora en pause et App Runner à 0,25 vCPU, [environ 60 $ par mois de plus](/fr/blog/aws-bill-of-a-three-person-startup) qu'un seul. C'est toute la prime, et c'est moins qu'une heure de l'ingénieur qui ferait sinon la migration du dix-huitième mois.

## Ce que vous obtenez le deuxième jour

La séparation n'est pas seulement une propriété de sécurité. C'est ce qui rend possibles plusieurs autres bonnes choses, et ce sont elles qui la financent :

- **[Les environnements de preview par pull request](/fr/blog/preview-environments-per-pull-request-on-aws)** ont besoin d'un endroit où n'importe qui peut déployer n'importe quoi sans demander. C'est le compte de dev, avec une trust policy OIDC permissive qui serait inacceptable en prod.
- **Un déploiement de production approuvé par un humain** a besoin d'un environnement GitHub avec des relecteurs, et d'un rôle que seul cet environnement peut assumer. C'est la trust policy du compte de prod.
- **Un suivi des coûts honnête.** « Combien coûte la production ? » est un filtre sur l'identifiant de compte, pas un projet d'archéologie à travers les tags.
- **Un rayon d'explosion pour les identifiants.** Une clé de dev qui fuit ne peut pas toucher les données de prod, parce qu'elle n'est pas dans ce compte. Nous avons [supprimé nos clés à longue durée de vie](/fr/blog/github-oidc-deploy-roles-per-aws-account) de toute façon, mais la frontière est la couche en dessous.
- **Un durcissement qui diffère par environnement sans branchement dans le code.** DESTROY en dev, RETAIN en prod, la récupération à un instant donné activée en staging et prod, depuis une seule table dans un seul fichier.

Rien de tout cela n'est possible dans un seul compte sans reconstruire l'isolation à la main à l'intérieur, avec des politiques IAM plus difficiles à réussir que la frontière de compte qu'elles imitent.

## Le cas à un seul compte qui est vraiment acceptable

Si vous construisez un prototype qui sera jeté dans huit semaines, un compte convient, et le séparer est du gaspillage. Le test, c'est de savoir s'il y a une base de données avec des données que vous seriez triste de perdre. Le jour où la réponse est oui est le jour où vous avez dépassé le prototype, et c'est généralement plus tôt que l'équipe ne le pense : la première fois qu'un vrai utilisateur s'inscrit, la première fois qu'une facture est générée, la première fois que quelqu'un dit « ne lance pas ça sur la vraie ».

Faites-le ce jour-là, pas le jour de l'incident.

Si vous avez un compte avec tout dedans et voulez la configuration du premier jour mise en place avant qu'elle ne devienne le projet du dix-huitième mois, [parlons-en](/contact). Nous avons fait les deux, et le premier est bien moins cher.
