Quand une limitation de plateforme change la façon de livrer

Nous sortons certaines APIs de notre monolithe vers AWS depuis un moment déjà, et la plupart de ces extractions sont restées volontairement peu dramatiques. API Gateway est devant, Cognito gère l'authentification quand il le faut, le mapping de requête structure le payload, puis une Lambda fait le travail. La plupart de ces morceaux sont assez isolés pour que le risque reste compréhensible et que le modèle opérationnel demeure simple.

Nous avons quand même fait une exception pragmatique pour un chemin de journalisation d'événements à fort volume. Celui-là a été déplacé derrière une Lambda function URL parce qu'API Gateway ne correspondait plus vraiment à la forme du trafic ni au modèle de coût. C'était un bon rappel que le travail dans le cloud ne consiste pas toujours à tout redessiner, mais souvent à apprendre où une plateforme cesse de bien correspondre à nos hypothèses.

Schéma d'architecture sombre montrant un pattern d'extraction de base où les clients passent par API Gateway vers une Lambda, avec une plus petite exception en function URL pour la journalisation d'événements.
La plupart des APIs extraites suivaient encore un pattern propre et assez simple. Le vrai problème est apparu plus tard, dans le modèle de livraison.

La Contrainte Était Petite. Son Impact Ne L'était Pas.

La partie plus intéressante est apparue quand nous avons dû déployer une Lambda@Edge. Notre pipeline reposait déjà sur un modèle de livraison auquel nous faisions confiance : on build pour le staging, on valide là, puis on promeut la même chose en production avec des valeurs propres à l'environnement injectées au moment du déploiement.

Lambda@Edge a cassé une partie de ce modèle parce qu'elle ne supporte pas les variables d'environnement. Sur papier, cela ressemble à un détail de plateforme. En pratique, cela a changé le sens même de la promotion. Si la production a besoin de valeurs différentes et que ces valeurs ne peuvent plus être injectées au déploiement, alors la promotion n'est peut-être plus vraiment une promotion. Elle devient peut-être une autre étape de build.

C'est là que se situait, pour moi, le vrai sujet d'architecture. Le code Lambda n'était pas la partie difficile. La partie difficile, c'est qu'une capacité manquante avait discrètement déplacé le modèle de confiance du processus de livraison. À partir de ce moment-là, on ne discute plus seulement d'implémentation. On décide du niveau de confiance de livraison qu'on veut préserver.

Le Compromis Portait Surtout sur la Confiance de Livraison

Nous avions trois options crédibles. La double build gardait un modèle de déploiement simple à opérer, mais elle affaiblissait l'identité de l'artifact parce que ce qui était validé en staging n'était plus évidemment exactement ce qui serait livré en production. L'approche par header gardait une seule build, mais déplaçait la sélection d'environnement dans le chemin d'exécution et transformait la configuration en préoccupation comportementale à l'intérieur de la fonction. Les layers préservaient un artifact unique testé et gardaient la configuration à l'extérieur du code, mais ajoutaient des objets opérationnels à versionner, attacher et maintenir compatibles entre les environnements.

Ce dernier point est important, parce que c'est là que l'approche par layers cessait d'être une réponse seulement élégante. Elle était plus propre du point de vue de l'intégrité de livraison, mais elle créait aussi plus de surface opérationnelle : cycle de vie des layers, suivi de version, et une couture de compatibilité supplémentaire entre code et configuration. La vraie décision n'était donc pas "meilleure architecture contre mauvaise architecture". C'était de savoir quel type de complexité l'équipe préférait assumer.

Schéma sombre de décision montrant la contrainte des variables d'environnement de Lambda@Edge, l'impact sur le modèle de livraison et une comparaison entre double build, routage par header et layers selon l'intégrité de l'artifact, la complexité d'exécution et le poids opérationnel.
La vraie question n'était pas de savoir quel contournement existait, mais où placer la complexité et ce qu'elle faisait à la confiance envers l'artifact.

Pourquoi Nous Avons Quand Même Choisi la Double Build

Au final, l'équipe a choisi une approche à double build, avec un ajustement qui rendait le risque plus acceptable : produire les deux artifacts propres aux environnements à partir de la même source, dans la même fenêtre de livraison. Cela ne rétablit pas une promotion pure, mais cela réduit la dérive accidentelle et garde un modèle opérationnel simple.

Je préfère encore l'approche par layers en principe parce qu'elle préserve la séparation la plus forte entre le code et l'environnement. Mais je ne pense pas que c'était une situation où une seule réponse pouvait être considérée comme sérieuse. Le chemin de la double build restait cohérent, suffisamment peu risqué dans le contexte réel, et plus simple à porter au quotidien pour l'équipe.

Le Principe que Je Retiens

Ce que je retiens n'est pas vraiment une leçon sur Lambda@Edge. C'est une leçon sur le design de livraison. Si une contrainte de plateforme change le fait que la production reçoive encore ou non le même artifact que celui validé plus tôt, il faut traiter cela comme un changement d'architecture, pas comme un simple irritant de pipeline. Cela touche la confiance, les hypothèses de rollback et les modes d'échec que l'équipe accepte.

Cela m'a aussi rappelé quelque chose de plus personnel. Il est facile de confondre préférence et principe quand les deux pointent dans la même direction. Si j'avais décidé seul, j'aurais probablement poussé vers les layers. Mais je ne décidais pas seul, et une partie du travail en équipe consiste à reconnaître qu'une solution peut ne pas être celle qu'on préfère tout en restant disciplinée, cohérente et suffisante pour avancer.

- Patrick