Skip to main content
infrastructure15 février 202615 min de lecture

Optimisation des coûts cloud : arrêtez de surpayer votre MVP

La plupart des startups gaspillent 40 à 60 % de leur budget cloud. Voici un guide pratique pour dimensionner correctement votre infrastructure sans sacrifier la fiabilité.

cloudawscost-optimization
Optimisation des coûts cloud : arrêtez de surpayer votre MVP

Le trimestre dernier, j'ai audité la facture AWS d'une startup et j'ai découvert qu'ils dépensaient 2 800 $/mois pour une infrastructure qui pourrait confortablement fonctionner pour 900 $. Ils avaient un t3.2xlarge exécutant une API Node.js qui culminait à 12 % d'utilisation CPU. Trois Elastic IPs inutilisées inactives à 3,65 $/mois chacune. Un déploiement RDS Multi-AZ pour une base de données de 200 lignes. Un NAT gateway routant du trafic qui aurait pu passer par un VPC endpoint gratuitement. Rien de tout cela n'était malveillant ni même particulièrement négligent — c'était l'accumulation de décisions "provisionnons juste quelque chose qui marche" prises pendant un sprint pour livrer.

C'est la norme, pas l'exception. La plupart des startups en phase initiale gaspillent 40 à 60 % de leurs dépenses cloud parce que personne dans l'équipe n'a le temps ou l'intérêt d'optimiser les coûts quand il y a des fonctionnalités à livrer. Le problème s'aggrave : une fois l'infrastructure provisionnée et fonctionnelle, personne n'y touche.

Les plus gros pièges de coûts que je vois constamment

Avant de plonger dans les solutions, il est utile de comprendre où va réellement l'argent. Voici les pièges que je rencontre le plus fréquemment en examinant l'infrastructure des startups.

Instances de calcul surdimensionnées

C'est la première source de gaspillage. Les équipes choisissent une taille d'instance lors de la configuration initiale — généralement basée sur un article de blog ou une mentalité "juste pour être sûr" — et ne la révisent jamais. J'ai vu des instances m5.xlarge exécuter des tâches cron qui s'exécutent pendant 30 secondes toutes les heures. L'instance reste inactive pendant 59,5 minutes, brûlant 0,192 $/heure (140 $/mois) pour ne rien faire.

La cause racine est psychologique : personne ne veut être la personne qui a sous-dimensionné le serveur et causé une panne. Alors tout le monde arrondit vers le haut. Deux fois.

# Check your EC2 instance CPU utilization over the past 2 weeks
aws cloudwatch get-metric-statistics \
  --namespace AWS/EC2 \
  --metric-name CPUUtilization \
  --dimensions Name=InstanceId,Value=i-0abcdef1234567890 \
  --start-time $(date -u -d '14 days ago' +%Y-%m-%dT%H:%M:%S) \
  --end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
  --period 3600 \
  --statistics Average Maximum

Si votre CPU moyen est inférieur à 20 % et votre pic inférieur à 50 %, vous êtes presque certainement surdimensionné. Descendez d'une ou deux tailles d'instance, surveillez pendant une semaine, et ajustez.

Volumes EBS et snapshots oubliés

Quand vous terminez une instance EC2, les volumes EBS attachés ne se suppriment pas automatiquement sauf si vous l'avez configuré au lancement. Cela signifie que les instances terminées laissent derrière elles des volumes orphelins qui continuent de facturer. J'ai vu des comptes avec des dizaines de volumes gp3 non attachés, chacun coûtant 0,08 $/Go/mois, totalisant des centaines de dollars pour du stockage que personne n'utilise.

Les snapshots sont encore plus sournois. Les scripts de sauvegarde automatisés créent des snapshots quotidiens sans politique de cycle de vie, donc ils s'accumulent indéfiniment. Un volume de 500 Go snapshoté quotidiennement pendant un an génère 365 snapshots, et bien que les snapshots EBS soient incrémentaux, les coûts s'additionnent pour devenir significatifs.

# Find all unattached EBS volumes
aws ec2 describe-volumes \
  --filters Name=status,Values=available \
  --query 'Volumes[*].{ID:VolumeId,Size:Size,Created:CreateTime}' \
  --output table

# Find snapshots older than 90 days
aws ec2 describe-snapshots \
  --owner-ids self \
  --query 'Snapshots[?StartTime<=`2025-12-01`].{ID:SnapshotId,Size:VolumeSize,Date:StartTime}' \
  --output table

NAT Gateway : le tueur silencieux de budget

Les NAT gateways coûtent 0,045 $/heure (32,40 $/mois) juste pour exister, plus 0,045 $ par Go de données traitées. Pour une startup faisant de fréquents appels API à des services externes depuis des sous-réseaux privés, les frais de traitement de données seuls peuvent dépasser 100 $/mois. J'ai vu les frais de NAT gateway représenter 15 à 20 % de la facture AWS totale d'une petite startup.

La solution dépend du trafic qui passe par le NAT :

  • Trafic vers les services AWS (S3, DynamoDB, SQS) : Utilisez les VPC Gateway Endpoints (gratuits pour S3 et DynamoDB) ou les Interface Endpoints (7,20 $/mois chacun, mais toujours moins cher que le NAT pour du trafic à haut volume).
  • Trafic vers internet depuis les fonctions Lambda : Demandez-vous si ces fonctions ont réellement besoin d'être dans un VPC. Beaucoup de fonctions Lambda sont placées dans un VPC "pour la sécurité" alors qu'elles n'accèdent à aucune ressource VPC.
  • Trafic sortant faible volume : Une instance NAT sur un t4g.nano (3,02 $/mois) gère un trafic modeste pour une fraction du coût du NAT gateway.

Frais de transfert de données

AWS facture 0,09 $/Go pour les données sortant d'une région, et le trafic inter-AZ coûte 0,01 $/Go dans chaque direction. Ces frais sont invisibles jusqu'à ce qu'ils ne le soient plus. Une architecture de microservices bavarde répartie sur trois zones de disponibilité, avec des services s'appelant les uns les autres des centaines de fois par seconde, peut générer des factures de transfert de données surprenantes.

La solution architecturale : co-localisez les services qui communiquent fréquemment dans la même AZ pour les charges de travail non critiques, ou utilisez des load balancers internes avec affinité AZ.

Dimensionnement correct : une approche systématique

Le dimensionnement correct n'est pas un exercice ponctuel. C'est quelque chose que vous devriez revoir trimestriellement. Voici le processus que je suis.

Étape 1 : Collecter les données d'utilisation

AWS Compute Optimizer est gratuit et fournit des recommandations de dimensionnement pour EC2, EBS, Lambda et ECS. Activez-le et laissez-le collecter au moins 14 jours de données avant d'agir sur ses recommandations.

Pour une analyse plus granulaire, les métriques CloudWatch sont votre source de données principale. Les métriques clés à surveiller :

  • EC2 : CPUUtilization, NetworkIn/Out, MemoryUtilization (nécessite l'agent CloudWatch)
  • RDS : CPUUtilization, DatabaseConnections, FreeableMemory, ReadIOPS, WriteIOPS
  • ElastiCache : CPUUtilization, CurrConnections, BytesUsedForCache

Étape 2 : Catégoriser les charges de travail

Toutes les charges de travail ne doivent pas être dimensionnées de la même façon. Je les catégorise en trois groupes :

Charges de travail stables (serveurs API, bases de données) : Elles ont besoin d'une capacité constante. Dimensionnez en trouvant la plus petite instance qui gère la charge de pointe avec 30 % de marge. Utilisez des Reserved Instances ou des Savings Plans pour la base.

Charges de travail variables (traitement par lots, serveurs de build) : Elles devraient utiliser des Auto Scaling Groups avec des politiques de mise à l'échelle appropriées, ou des Spot Instances pour les jobs batch tolérants aux pannes.

Charges de travail périodiques (tâches cron, rapports planifiés) : Elles ne devraient pas du tout fonctionner sur des instances dédiées. Migrez-les vers Lambda, Fargate Spot, ou Step Functions.

Étape 3 : Agir de manière incrémentale

Ne redimensionnez jamais tout en une fois. Descendez d'une taille d'instance à la fois, surveillez pendant une semaine, puis décidez s'il faut aller plus loin. Le coût d'une brève période de surdimensionnement est bien inférieur au coût d'une panne de production causée par un redimensionnement agressif.

Reserved Instances vs Savings Plans vs Spot

C'est là que les vraies économies se font — 30 à 72 % de réduction par rapport au tarif à la demande — mais les mécaniques d'engagement sont assez confuses pour que de nombreuses startups les évitent complètement.

Reserved Instances (RIs)

Vous vous engagez sur un type d'instance spécifique dans une région spécifique pour 1 ou 3 ans. En échange, vous obtenez 30 à 40 % de réduction (sans acompte, 1 an) à 60 % de réduction (tout payé d'avance, 3 ans). Le piège : si vous devez changer de type d'instance, les RIs Standard ne sont pas flexibles. Les RIs Convertibles offrent plus de flexibilité avec une remise légèrement inférieure (environ 45 % pour 3 ans tout payé d'avance).

Quand utiliser les RIs : Bases de données et autres charges de travail où le type et la taille d'instance sont réellement stables. Les RDS Reserved Instances en valent presque toujours la peine — les bases de données changent rarement de taille.

Savings Plans

Les Savings Plans sont l'alternative moderne aux RIs pour le calcul. Vous vous engagez sur un montant en dollars de calcul par heure (par exemple, 0,10 $/heure) pour 1 ou 3 ans. L'engagement s'applique automatiquement à l'utilisation EC2, Fargate et Lambda, et il est flexible entre les familles d'instances, les tailles, les OS et les régions.

Quand utiliser les Savings Plans : Presque toujours préférables aux EC2 RIs pour les charges de travail de calcul. Les Compute Savings Plans offrent le meilleur ratio flexibilité/remise. Commencez par un engagement qui couvre vos dépenses de base minimales.

# Example: Calculating Savings Plan commitment
# Current on-demand spend: $500/month on EC2
# Minimum baseline (never drops below): $350/month
# Recommended Savings Plan commitment: $350/month = ~$0.48/hour
# Expected savings: ~30% on the committed amount = ~$105/month
# Remaining $150/month stays on-demand for flexibility

Spot Instances

Les Spot Instances offrent des remises de 60 à 90 % mais peuvent être interrompues avec un préavis de 2 minutes. Elles sont idéales pour :

  • Les agents de build CI/CD (utilisez Spot Fleet avec plusieurs types d'instances)
  • Les jobs de traitement par lots qui peuvent faire des checkpoints et reprendre
  • Les environnements de développement et de staging
  • Les tests de charge

Elles ne sont pas adaptées aux serveurs API de production, aux bases de données, ou à quoi que ce soit qui ne peut pas gérer une interruption soudaine.

# Example: GitHub Actions self-hosted runner on Spot
# This saves roughly 70% compared to GitHub-hosted runners
# for compute-heavy builds
Resources:
  SpotFleet:
    Type: AWS::EC2::SpotFleet
    Properties:
      SpotFleetRequestConfigData:
        IamFleetRole: !GetAtt SpotFleetRole.Arn
        TargetCapacity: 2
        AllocationStrategy: lowestPrice
        LaunchSpecifications:
          - InstanceType: c5.xlarge
            SpotPrice: "0.06"
          - InstanceType: c5a.xlarge
            SpotPrice: "0.06"
          - InstanceType: c6i.xlarge
            SpotPrice: "0.06"

Modèles de coûts serverless : pas toujours moins cher

Il existe un mythe persistant selon lequel le serverless est toujours moins cher pour les startups. C'est souvent moins cher à faible échelle, mais l'économie s'inverse à mesure que le trafic augmente.

La réalité des prix Lambda

Lambda facture par requête (0,20 $ par million) et par Go-seconde de calcul (0,0000166667 $). Pour un endpoint API typique qui s'exécute en 200ms avec 256 Mo de mémoire :

  • 1 000 requêtes/jour : ~0,03 $/mois. Effectivement gratuit.
  • 100 000 requêtes/jour : ~3,00 $/mois. Toujours très bon marché.
  • 1 000 000 requêtes/jour : ~30 $/mois. Commence à se comparer à une petite instance EC2.
  • 10 000 000 requêtes/jour : ~300 $/mois. Un t3.medium (30 $/mois) avec un bon cache gère cela facilement.

Le point de croisement dépend fortement de la durée d'exécution et de l'allocation mémoire, mais pour la plupart des charges API, Lambda cesse d'être rentable quelque part entre 1 et 5 millions de requêtes par jour. En dessous de ce seuil, c'est presque toujours l'option la moins chère.

Les coûts d'API Gateway s'accumulent

Les gens oublient que les fonctions Lambda derrière API Gateway engendrent des frais supplémentaires. API Gateway coûte 3,50 $ par million de requêtes (API REST) ou 1,00 $ par million (API HTTP). À grande échelle, le coût d'API Gateway dépasse le coût Lambda. Si vous avez suffisamment de trafic pour vous soucier des coûts Lambda, vous devriez utiliser un Application Load Balancer (0,008 $ par heure-LCU) au lieu d'API Gateway.

Fargate : le juste milieu

AWS Fargate se situe entre Lambda et EC2 en termes de coût et de complexité opérationnelle. Vous payez le vCPU et la mémoire à la seconde, sans gestion d'instance. Pour les charges de travail qui doivent fonctionner en continu mais dont vous ne voulez pas gérer les serveurs, Fargate avec des fournisseurs de capacité Spot offre un bon équilibre.

Une tâche Fargate avec 0,25 vCPU et 0,5 Go de mémoire coûte environ 9 $/mois en fonctionnement continu. C'est compétitif avec un t4g.nano et vous bénéficiez du placement automatique, des health checks et de la mise à l'échelle sans gérer l'hôte sous-jacent.

Surveillance et alertes sur les coûts

Vous ne pouvez pas optimiser ce que vous ne mesurez pas. Voici la stack de surveillance que je mets en place pour chaque projet.

AWS Cost Explorer

Activez Cost Explorer et configurez un budget mensuel avec des alertes à 50 %, 80 % et 100 % du seuil. C'est le strict minimum. La vue "Coût par service" de Cost Explorer montre immédiatement où va l'argent.

# Create a budget with email alerts
aws budgets create-budget \
  --account-id 123456789012 \
  --budget '{
    "BudgetName": "Monthly-Total",
    "BudgetLimit": {"Amount": "500", "Unit": "USD"},
    "TimeUnit": "MONTHLY",
    "BudgetType": "COST"
  }' \
  --notifications-with-subscribers '[{
    "Notification": {
      "NotificationType": "ACTUAL",
      "ComparisonOperator": "GREATER_THAN",
      "Threshold": 80,
      "ThresholdType": "PERCENTAGE"
    },
    "Subscribers": [{
      "SubscriptionType": "EMAIL",
      "Address": "team@startup.com"
    }]
  }]'

Infracost pour l'Infrastructure as Code

Si vous utilisez Terraform, Infracost s'intègre dans votre pipeline CI et affiche des estimations de coûts pour chaque changement d'infrastructure avant qu'il ne soit appliqué. C'est transformateur — cela déplace la conscience des coûts d'une surprise mensuelle à une conversation de pull request.

# .github/workflows/infracost.yml
name: Infracost
on: pull_request
jobs:
  infracost:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Setup Infracost
        uses: infracost/actions/setup@v3
        with:
          api-key: ${{ secrets.INFRACOST_API_KEY }}
      - name: Generate cost estimate
        run: |
          infracost breakdown --path=. \
            --format=json --out-file=/tmp/infracost.json
          infracost comment github \
            --path=/tmp/infracost.json \
            --repo=$GITHUB_REPOSITORY \
            --pull-request=${{ github.event.pull_request.number }} \
            --github-token=${{ secrets.GITHUB_TOKEN }}

Détection d'anomalies de coûts

AWS Cost Anomaly Detection utilise le machine learning pour identifier les patterns de dépenses inhabituels. C'est gratuit et envoie des alertes quand les dépenses dévient des patterns historiques. Activez-le pour chaque service et configurez des notifications SNS vers Slack.

Patterns architecturaux qui font économiser

Au-delà du dimensionnement individuel des ressources, certaines décisions architecturales changent fondamentalement votre structure de coûts.

Mise en cache agressive

Une distribution CloudFront devant votre API pour les réponses cachables coûte 0,085 $/10 000 requêtes HTTPS et 0,085 $/Go de transfert — mais elle élimine ces requêtes de votre backend. Pour les API à forte lecture (ce qui est le cas de la plupart), un taux de cache hit de 90 % signifie que votre backend gère 10 fois moins de trafic.

Encore plus simple : un cache en mémoire comme Redis ou juste un cache LRU local dans votre application peut éliminer les requêtes de base de données redondantes. J'ai vu les coûts de base de données chuter de 60 % après avoir ajouté un cache de 15 minutes sur les 5 endpoints les plus fréquemment consultés.

Utiliser S3 intelligemment

S3 propose plusieurs classes de stockage, et utiliser la bonne est important :

Classe de stockage Coût/Go/mois Cas d'utilisation
S3 Standard 0,023 $ Données actives, accès fréquent
S3 Infrequent Access 0,0125 $ Sauvegardes, logs de plus de 30 jours
S3 Glacier Instant 0,004 $ Archives nécessitant un accès immédiat
S3 Glacier Deep Archive 0,00099 $ Archives long terme, accès rare

Configurez des S3 Lifecycle Policies pour transitionner automatiquement les objets entre les classes de stockage :

{
  "Rules": [
    {
      "ID": "TransitionToIA",
      "Status": "Enabled",
      "Transitions": [
        {
          "Days": 30,
          "StorageClass": "STANDARD_IA"
        },
        {
          "Days": 90,
          "StorageClass": "GLACIER_INSTANT_RETRIEVAL"
        }
      ]
    }
  ]
}

Services managés vs auto-hébergés

Ce compromis est nuancé. Les services managés (RDS, ElastiCache, OpenSearch Service) coûtent plus par unité de calcul que l'auto-hébergement sur EC2, mais ils incluent les correctifs, les sauvegardes, le basculement et la surveillance. Pour une startup sans personne dédiée aux opérations, le temps d'ingénierie économisé justifie presque toujours le surcoût.

L'exception : les services managés aux niveaux les plus élevés. Une instance RDS db.r6g.2xlarge coûte significativement plus que l'instance EC2 équivalente exécutant PostgreSQL. Une fois que vous avez une équipe capable de gérer les opérations et que vous dépensez plus de 1 000 $/mois sur un seul service managé, il vaut la peine d'évaluer l'auto-hébergement.

Consolider quand c'est possible

Exécuter des instances RDS séparées pour les environnements de staging, QA et développement est coûteux. Options :

  • Utilisez une seule instance RDS avec des bases de données séparées pour les environnements hors production.
  • Utilisez Aurora Serverless v2 pour dev/staging — il se réduit à zéro quand il est inactif.
  • Exécutez les bases de données de développement sur une seule EC2 Spot Instance avec Docker.

Un vrai guide d'optimisation des coûts

Voici le processus étape par étape que je suis quand je prends en charge un projet d'optimisation des coûts. Cela permet généralement d'obtenir 30 à 50 % d'économies dès le premier mois.

Semaine 1 : Audit

  1. Activer AWS Cost Explorer s'il n'est pas déjà actif.
  2. Extraire un détail des coûts sur 3 mois par service.
  3. Identifier les 5 principaux services par dépense.
  4. Exécuter AWS Compute Optimizer et Trusted Advisor.
  5. Lister tous les volumes EBS non attachés, les Elastic IPs inutilisées et les load balancers inactifs.

Semaine 2 : Gains rapides

  1. Supprimer les ressources inutilisées identifiées dans l'audit.
  2. Redimensionner les instances les plus surdimensionnées (1 taille en dessous, surveiller).
  3. Configurer les VPC endpoints pour le trafic S3 et DynamoDB.
  4. Activer les S3 Lifecycle Policies sur tous les buckets.
  5. Configurer les alertes de budget.

Semaine 3 : Engagements

  1. Analyser les charges de travail stables pour l'éligibilité aux Savings Plans.
  2. Acheter des Compute Savings Plans pour les dépenses de calcul de base.
  3. Acheter des RDS Reserved Instances pour les bases de données de production.
  4. Convertir les charges de travail adaptées en Spot Instances.

Semaine 4 : Architecture

  1. Ajouter des couches de cache là où c'est approprié.
  2. Évaluer la migration serverless pour les charges de travail adaptées.
  3. Consolider les environnements hors production.
  4. Configurer Infracost dans le pipeline CI.
  5. Documenter la base de coûts pour la surveillance continue.

Ce qu'il ne faut pas optimiser

L'optimisation des coûts a des rendements décroissants, et certaines "économies" créent plus de problèmes qu'elles n'en résolvent.

Ne sacrifiez pas la fiabilité pour les coûts. Exécuter une base de données de production sur un déploiement single-AZ pour économiser sur les frais Multi-AZ est une fausse économie. La première panne coûtera plus que des années de surcoût Multi-AZ.

Ne sur-optimisez pas pour l'échelle actuelle. Si votre startup croît de 20 % par mois, passer une semaine à optimiser un service à 50 $/mois n'est pas une bonne utilisation du temps. Concentrez-vous sur les postes importants.

Ne vous battez pas contre le modèle tarifaire du fournisseur cloud. AWS est conçu pour être cher si vous allez à l'encontre de ses conventions. Utilisez les services managés comme ils sont prévus, profitez des offres gratuites et tirez parti des remises d'engagement qu'ils offrent. Essayer de contourner la tarification avec des architectures trop astucieuses se retourne généralement contre vous.

Ne supprimez pas la surveillance pour économiser. CloudWatch coûte de l'argent, mais naviguer à l'aveugle coûte plus cher. Les 15 $/mois que vous dépensez en surveillance détaillée vous épargneront la surprise de 500 $ que la surveillance détaillée aurait détectée.

L'effet composé

Le meilleur argument pour une optimisation précoce des coûts n'est pas les économies immédiates — ce sont les habitudes et l'infrastructure que vous mettez en place. Une startup qui configure des alertes de budget, utilise Infracost dans le CI et revoit les coûts mensuellement maintiendra une infrastructure efficace en grandissant. Une startup qui ignore les coûts jusqu'à la série B se retrouvera avec des factures AWS de 30 000 $/mois qui nécessitent six mois d'effort dédié pour les démêler.

Commencez par l'audit. Les chiffres vous indiqueront où concentrer vos efforts.

DU

Danil Ulmashev

Full Stack Developer

Intéressé par une collaboration ?