Home .NET Aspire : l’orchestrateur qui simplifie vos applications distribuées

Aspire : l’orchestrateur qui simplifie vos applications distribuées

  Clément Caillaud 15 min 24 juillet 2026

Trois terminaux ouverts, un service qui plante parce que la base de données n’était pas prête à temps, et dix minutes perdues avant même d’écrire une ligne de code : la scène est familière à quiconque a déjà touché à une architecture distribuée. Aspire promet d’y mettre fin en une seule commande. Reste à savoir si la promesse tient.

Le casse-tête du dev local face à une architecture microservices

Une application moderne tient rarement dans un seul processus. Elle s’appuie sur un frontend (Angular, React…), une ou plusieurs API, une base de données et un cache. S’y ajoutent parfois une queue de messages, et de plus en plus souvent des services cloud. En production, cette complexité est gérée par de l’infrastructure dédiée. En développement local, en revanche, c’est une autre histoire.

Plusieurs terminaux, un ordre de démarrage à respecter, et l’espoir que rien n’ait changé depuis la dernière fois. Des douleurs plus insidieuses se cachent ailleurs : des chaînes de connexion comme localhost:5432 codées en dur, qui cassent dès qu’on change de machine ou qu’on déploie. Des configurations locales qui divergent d’un développeur à l’autre, avec le fameux « ça marche sur ma machine ». Un débogage qui oblige à jongler entre plusieurs terminaux et plusieurs dashboards dès qu’un bug traverse deux services. Et un nouveau venu dans l’équipe qui doit installer et configurer son environnement à la main, avant même d’écrire sa première ligne de code.

En somme, c’est précisément ces problèmes qu’Aspire résout.

Comparaison avant et après Aspire

Qu’est-ce qu’Aspire ?

Aspire (anciennement .NET Aspire) est une couche d’orchestration et d’observabilité, code-first, pour les applications distribuées. En une phrase : c’est un outil qui permet de décrire toute son architecture dans du code, puis de la lancer d’une seule commande. On peut ensuite l’observer dans un dashboard, et déployer ce même modèle en production.

Le nom vient de .NET, mais l’outil ne s’y limite pas. En effet, le fichier qui décrit l’architecture (l’AppHost) s’écrit aujourd’hui en C# ou en TypeScript. Les services qu’il orchestre peuvent quant à eux être écrits dans un langage différent : .NET, JavaScript, Python et Go sont pris en charge officiellement, tandis que Java, Rust ou PowerShell le sont via le Community Toolkit (des intégrations maintenues par la communauté plutôt que par l’équipe Aspire). Cette ouverture multi-langage n’est d’ailleurs pas un hasard : elle reflète le modèle de développement du projet.

En effet, c’est aussi un projet open source, publié sous licence MIT sur GitHub. L’équipe Microsoft en pilote la feuille de route, mais chaque version intègre des contributions externes concrètes. Le Community Toolkit évoqué plus haut prolonge cette logique : rattaché à la .NET Foundation, il permet à la communauté d’ajouter ses propres intégrations sans attendre qu’elles rejoignent le catalogue officiel.

Il est aussi utile de préciser ce qu’Aspire n’est pas, pour éviter les malentendus :

  • Ce n’est pas un framework applicatif : il ne remplace pas .NET, Angular ou Express.
  • Ce n’est pas un cloud provider ni un runtime de production.
  • Ce n’est pas un remplaçant de Docker ou Kubernetes : il s’appuie dessus plutôt que de les concurrencer.

Concrètement, Aspire se résume à quatre gestes fondamentaux : décrire l’architecture dans l’AppHost, lancer tout avec aspire run, observer dans le Dashboard, puis déployer le même modèle en production.

Comment ça fonctionne concrètement ?

L’AppHost, le plan de votre application

L’AppHost est le point d’entrée de tout : un projet de code qui déclare l’ensemble de l’architecture. Il remplace ainsi les scripts bash, les fichiers docker-compose éparpillés et les pages de wiki « comment installer le projet ».

On y déclare notamment des ressources, c’est-à-dire tout ce qui compose l’application, quel que soit son langage :

  • Projets .NET (AddProject<T>()) ;
  • Applications JavaScript ou Node (AddNpmApp(), AddViteApp()) ;
  • Applications Python (AddPythonApp()) ;
  • Containers Docker (AddContainer(), AddDockerfile()) ;
  • Bases de données (AddPostgres(), AddSqlServer(), AddMongoDB()…) ;
  • Caches et queues (AddRedis(), AddRabbitMQ(), AddKafka()…) ;
  • Services cloud (Azure Service Bus, Cosmos DB, Key Vault…).

On y déclare aussi les relations entre ces ressources avec .WithReference(), et Aspire se charge de câbler les connexions.

Un exemple concret pour une application Angular + API .NET + Redis :

AppHost annoté

Une dizaine de lignes pour décrire toute l’architecture. Ainsi, ce fichier versionné devient la source de vérité unique : toute l’équipe lance exactement le même environnement, sans divergence.

Service discovery : la fin des URLs codées en dur

Le problème classique : quand un service doit en appeler un autre, il lui faut une adresse. En local on écrit localhost:5001, en CI c’est autre chose, en production encore autre chose. Autant de configurations à maintenir, et autant de sources d’erreur.

Aspire résout ça avec un service discovery automatique. Concrètement, dès qu’on déclare .WithReference(api) dans l’AppHost, Aspire injecte la bonne URL dans les variables d’environnement du service qui en dépend. Dans le code de l’application, on ne référence donc plus jamais une adresse : on référence le nom logique déclaré dans l’AppHost.

Service discovery
Résultat : le même code fonctionne en local, en CI et en production, ce qui élimine toute une classe de bugs liés aux différences de configuration entre environnements.

Un socle commun pour tous les services

Service Defaults : l’essentiel prêt à l’emploi

Dans une application distribuée, chaque service a besoin des mêmes comportements transverses : logs, traces, métriques, health checks, résilience. Sans outillage partagé, on finit donc par les configurer à la main dans chaque projet, et cette configuration dérive avec le temps.
Pour répondre à ce besoin, Aspire introduit un projet Service Defaults, partagé par tous les services de la solution. Deux appels suffisent dans chaque service : un dans Program.cs, l’autre juste après la construction de l’application :

Service defaults

Ensemble, ces deux appels configurent l’instrumentation OpenTelemetry (logs, traces, métriques) et la résolution du service discovery. Ils activent aussi des retry policies et circuit breakers par défaut, ainsi que les endpoints de health check /health et /alive. À noter : par défaut, ces deux derniers endpoints ne sont exposés qu’en environnement de développement, pour des raisons de sécurité. Les activer en production reste possible, mais demande une démarche volontaire. Le projet Service Defaults reste néanmoins dans votre dépôt et est personnalisable : ce n’est pas une boîte noire.

Un large éventail d’intégrations

C’est d’ailleurs ce socle qui rend les intégrations d’Aspire cohérentes entre elles. Le catalogue officiel couvre un large éventail de technologies, réparties en deux familles. D’une part, les hosting integrations, déclarées dans l’AppHost, qui provisionnent la ressource (par exemple AddRedis("cache") démarre un container Redis versionné). D’autre part, les client integrations, configurées côté application, qui branchent le client avec health check et traces déjà prêts (AddRedisClient("cache")). En réalité, rien de magique derrière : ce sont simplement des patterns connus, appliqués de façon automatique et cohérente.

Concrètement, ce catalogue couvre la plupart des besoins qu’on rencontre sur un projet distribué : caching (Redis, Valkey, Garnet), bases de données (PostgreSQL, SQL Server, MongoDB, MySQL, CosmosDB, Oracle…), et messaging (RabbitMQ, Kafka, NATS, Azure Service Bus…). On y trouve aussi des services cloud Azure (Container Apps, App Service, Key Vault, Blob Storage…), des outils d’IA (OpenAI, Azure OpenAI…), de la sécurité (Keycloak), ou encore des outils de développement (Seq). Le Community Toolkit ajoute par ailleurs des intégrations qui n’entrent pas (encore) dans le catalogue officiel, comme Mailpit (tester l’envoi d’e-mails en local), Ollama (modèles d’IA en local), Meilisearch (moteur de recherche) ou k6 (tests de charge). Et si une brique n’existe pas dans le catalogue, rien n’empêche de la déclarer soi-même comme un simple container Docker.

Le Dashboard : tout voir au même endroit

Le Dashboard se lance automatiquement dès qu’on fait aspire run, sans aucune configuration. C’est la vitrine de tout ce que les composants précédents ont instrumenté.

On y trouve la liste des ressources avec leur état en temps réel (Running, Starting, Error), avec la possibilité de les redémarrer directement depuis l’interface. S’y ajoutent les logs structurés de tous les services, agrégés et filtrables, ainsi que les traces distribuées, qui permettent de suivre une requête en cascade à travers plusieurs services. Le Dashboard affiche enfin les métriques (CPU, mémoire, latence, requêtes par seconde) et la configuration de chaque service, utile pour vérifier qu’une chaîne de connexion a bien été injectée.

Dashboard ressources

OpenTelemetry : un standard ouvert, pas un enfermement

Tout ce que le Dashboard affiche repose sur OpenTelemetry, un standard ouvert et largement adopté dans l’industrie plutôt qu’une technologie propriétaire à Aspire. Concrètement, les logs peuvent être exportés vers Seq ou une stack ELK, les traces vers Jaeger ou Grafana Tempo, et les métriques vers Prometheus ou Grafana.

Ce point compte plus qu’il n’y paraît : en effet, ce qui est visible en développement dans le Dashboard peut être observé exactement de la même façon en production, avec les outils que l’équipe ops utilise déjà. Il n’y a donc pas un système d’observabilité pour le dev et un autre pour la prod : c’est le même standard, bout en bout.

Un exemple concret : Angular, API .NET et Redis

Pour illustrer tout ça sur autre chose qu’un extrait isolé, voici un exemple de projet de démonstration, une application composée d’un frontend Angular, d’une API .NET et d’un cache Redis. Le code complet est disponible sur ce dépôt GitHub si vous voulez le faire tourner chez vous.

L’AppHost déclare les trois ressources et leurs dépendances :

Demo AppHost

Côté API, deux lignes suffisent pour brancher les Service Defaults et le client Redis :

Démo api

Une seule commande démarre toute la stack, dans le bon ordre, avec les dépendances correctement câblées (ou simplement F5 depuis Visual Studio) : aspire run

Le Dashboard s’ouvre automatiquement et affiche les trois ressources en cours de démarrage. Une fois tout démarré, une requête envoyée depuis le frontend traverse l’API puis Redis. Cette traversée est visible dans le Dashboard sous forme de trace distribuée : chaque étape, sa durée, ses éventuelles erreurs.

Dashboard traces

Aller plus loin : une commande personnalisée dans le Dashboard

Le Dashboard ne sert pas qu’à observer passivement : on peut aussi y ajouter des commandes personnalisées directement sur une ressource. Un scénario courant avec du cache : l’API sert une donnée depuis Redis. Si cette donnée est modifiée directement en base, l’API continue à répondre avec la version mise en cache tant qu’elle n’a pas expiré.

Plutôt que de redémarrer l’API à chaque test, on peut ajouter un bouton « Vider le cache » directement utilisable depuis le Dashboard :

Custom command : Clear cache

Vider le cache dans le dashboard

Concrètement : on modifie une donnée en base, le frontend affiche toujours l’ancienne valeur, servie par le cache. On clique alors sur « Vider le cache » dans le Dashboard, et l’appel suivant va chercher la donnée à jour. Ce genre de commande personnalisée transforme ainsi le Dashboard en véritable outil de debug métier, pas seulement en tableau d’observabilité passive.

C’est ce genre de visibilité immédiate, sans aucune configuration manuelle nécessaire, qui change concrètement le quotidien. Un bug qui traverse deux services ne demande alors plus de jongler entre plusieurs terminaux : il s’inspecte au même endroit. Par ailleurs, si on modifie le code de l’API pendant que la stack tourne, le hot reload s’applique sans avoir à tout redémarrer manuellement. Au final, c’est l’un de ces petits détails qui, cumulés, font gagner du temps sur une journée de développement.

Et en production ?

L’AppHost n’est pas qu’un outil de développement : c’est aussi le modèle de déploiement. Ainsi, la même définition d’architecture sert du poste local jusqu’à la production, ce qui évite les dérives de configuration entre les environnements.

Pour cela, deux commandes permettent de passer à l’action. Toutes deux sont encore signalées comme Preview dans la CLI Aspire au moment de la rédaction (24/07/2026), ce qui signifie que certains détails de fonctionnement peuvent encore évoluer d’une version à l’autre.

aspire publish : la CI/CD garde la main

aspire publish génère des fichiers de déploiement adaptés à la cible choisie : un docker-compose.yaml, des manifests Kubernetes, ou des templates Bicep pour Azure. Cette commande ne résout toutefois pas les secrets. C’est ensuite un pipeline CI/CD, ou une équipe ops, qui reprend ces artefacts pour y injecter les vraies valeurs et déclencher le déploiement. Ce pattern reste le plus courant pour une production sérieuse, avec approbations et traçabilité.

aspire deploy : tout-en-un

aspire deploy, à l’inverse, fait tout en une seule commande : il exécute lui-même l’étape de publication en interne, résout les paramètres, puis applique le déploiement directement vers la cible. Cette approche est utile pour un déploiement direct depuis un poste de développement, ou depuis un runner CI simple. Les secrets, dans ce cas, sont injectés via les variables d’environnement du runner, exactement comme on le fait déjà pour un appsettings.json :

GitHub Action deploy

Les cibles de déploiement disponibles

La cible de déploiement se déclare directement dans l’AppHost, pas en argument de commande :

Cible déploiement

Cible Ce qu’Aspire génère
Docker Compose Un fichier docker-compose.yaml et son .env
Kubernetes / AKS Des Helm charts ou manifests déployables sur tout cluster
Azure Container Apps Des templates Bicep, avec provisioning de l’infra et des identités managées
Azure App Service Des templates Bicep équivalents pour ce mode d’hébergement

Dans tous les cas, c’est le pipeline CI/CD (ou l’ops qui l’exécute) qui décide quand déployer et avec quelles autorisations. Aspire, de son côté, décide quoi déployer et dans quel ordre, à partir de la même définition d’architecture que celle utilisée en local.

Conclusion

Limites et points de vigilance

Aspire simplifie beaucoup de choses, mais quelques points méritent d’être gardés à l’esprit avant de se lancer.

  • L’écosystème est encore jeune. Le catalogue d’intégrations grandit vite, mais il n’a pas encore la maturité d’un docker-compose éprouvé depuis des années sur certains cas très spécifiques.
  • Ça ne dispense pas de comprendre l’infrastructure sous-jacente. Aspire génère en effet des fichiers Bicep, des charts Helm ou des configurations Docker Compose. Il reste utile de savoir lire ce qui est produit, surtout en production.
  • L’AppHost et les Service Defaults demandent un vrai investissement initial, comme tout socle partagé : bien les structurer dès le départ évite d’avoir à les refactoriser plus tard.

Ce qu’Aspire apporte concrètement

En reprenant les points précédents, les gains se situent à trois niveaux différents, pour trois publics différents.

  • Côté développeurs, au quotidien : un seul aspire run (ou F5) pour démarrer toute la stack, fini les wikis de setup et les enchaînements de commandes à retenir.
  • Pour les équipes, à l’échelle du projet : l’AppHost fait office de documentation vivante de l’architecture, versionnée avec le code. Elle ne peut pas devenir obsolète, puisque c’est elle qui fait tourner l’application.
  • Jusqu’en production, pour les ops : le même modèle sert du poste local au déploiement, avec une observabilité basée sur un standard ouvert plutôt que sur un outil propriétaire.

Alors, faut-il adopter Aspire ?

Aspire ne remplace ni votre framework, ni Docker, ni votre pipeline CI/CD. Il comble un vide précis : celui du développement local d’une application distribuée, où l’orchestration, la configuration et l’observabilité étaient jusque-là laissées à la débrouille de chaque développeur.

La vraie question n’est donc pas « Aspire est-il un bon outil ? », mais « ai-je le problème qu’il résout ? ». Quelques signaux indiquent que oui :

  • Vous lancez plus d’un service en local (frontend, API, base, cache…) ;
  • L’équipe veut normaliser l’environnement de développement, sans wiki de setup ni « ça marche sur ma machine » ;
  • Besoin de traçabilité et d’observabilité, sans configurer OpenTelemetry à la main dans chaque service.

À l’inverse, sur un monolithe unique, ou si l’équipe n’a pas le temps d’investir dès le départ dans un AppHost et des Service Defaults bien structurés, le gain reste marginal à court terme : mieux vaut alors attendre que l’architecture se complexifie réellement avant de s’y mettre.

Pour un projet déjà existant, pas besoin de trancher tout de suite : la commande aspire add permet d’intégrer Aspire progressivement, service par service, sans réécriture.

Au final, dès que ces signaux sont réunis, Aspire est un pari raisonnable : le ticket d’entrée est faible, et le bénéfice grandit avec le nombre de services. En ramenant l’orchestration et l’observabilité dans du code versionné, Aspire transforme l’architecture d’une application en documentation vivante. Un simple aspire run remplace désormais une poignée de terminaux ouverts en parallèle.

 


Pour aller plus loin :

Le code de la démo présentée dans cet article est disponible sur github.com/ClementCaillaud/DemoAspire.

Lire les articles similaires

Laisser un commentaire

Social Share Buttons and Icons powered by Ultimatelysocial