{"id":1276,"date":"2026-03-12T09:29:16","date_gmt":"2026-03-12T12:29:16","guid":{"rendered":"https:\/\/maurobernal.com.ar\/blog\/?p=1276"},"modified":"2026-03-12T09:29:16","modified_gmt":"2026-03-12T12:29:16","slug":"arquitectura-web-api-dotnet-10-parte-3","status":"publish","type":"post","link":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/","title":{"rendered":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real"},"content":{"rendered":"\n<p>Llegamos a la tercera y \u00faltima parte de la serie <strong>Arquitectura Esencial de Web APIs en .NET 10<\/strong>. En la <a href=\"\/arquitectura-web-api-dotnet-10-parte-1\">Parte 1<\/a> vimos los fundamentos, en la <a href=\"\/arquitectura-web-api-dotnet-10-parte-2\">Parte 2<\/a> los componentes de performance y escalabilidad. Ahora cerramos con los cuatro que elevan una API de \u00abfuncional\u00bb a \u00abprofesional\u00bb: observabilidad, resiliencia, despliegue progresivo y comunicaci\u00f3n en tiempo real.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">8. OpenTelemetry: ver lo que pasa adentro<\/h2>\n\n\n\n<p>Tuve a\u00f1os en los que mi \u00abmonitoreo\u00bb consist\u00eda en revisar logs manualmente y rezar para encontrar el error antes de que me llamara el cliente. Hoy, con OpenTelemetry integrado nativamente en .NET 10, no hay excusa para no tener observabilidad completa desde el d\u00eda uno.<\/p>\n\n\n\n<p>OpenTelemetry unifica tres pilares de observabilidad:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Trazas distribuidas:<\/strong> seguir el flujo de una request a trav\u00e9s de m\u00faltiples servicios<\/li>\n<li><strong>M\u00e9tricas:<\/strong> CPU, memoria, requests por segundo, latencia<\/li>\n<li><strong>Logs:<\/strong> correlacionados autom\u00e1ticamente con las trazas<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">builder.Services.AddOpenTelemetry()\n    .WithMetrics(metrics => metrics\n        .AddAspNetCoreInstrumentation()   \/\/ M\u00e9tricas de HTTP\n        .AddRuntimeInstrumentation()      \/\/ GC, threadpool, memoria\n        .AddPrometheusExporter())         \/\/ Expone \/metrics para Prometheus\n    .WithTracing(tracing => tracing\n        .AddAspNetCoreInstrumentation()   \/\/ Trazas de requests HTTP\n        .AddHttpClientInstrumentation()   \/\/ Trazas de llamadas salientes\n        .AddEntityFrameworkCoreInstrumentation() \/\/ Trazas de queries SQL\n        .AddOtlpExporter(otlp =>          \/\/ Exporta a Jaeger, Grafana Tempo, etc.\n        {\n            otlp.Endpoint = new Uri(\"http:\/\/localhost:4317\");\n        }));\n\n\/\/ Opcional: exponer el endpoint de m\u00e9tricas de Prometheus\napp.MapPrometheusScrapingEndpoint(\"\/metrics\");<\/code><\/pre>\n\n\n\n<p>Una vez que ten\u00e9s OpenTelemetry configurado, herramientas como <strong>Grafana + Prometheus + Tempo<\/strong> te dan dashboards completos, alertas autom\u00e1ticas y trazas distribuidas entre microservicios. Todo lo que necesit\u00e1s para diagnosticar cualquier problema en producci\u00f3n en minutos en lugar de horas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">9. Resiliencia con Polly: sobrevivir a las ca\u00eddas externas<\/h2>\n\n\n\n<p>En arquitecturas de microservicios hay una certeza: el servicio que llam\u00e1s va a fallar en alg\u00fan momento. No es una posibilidad, es una garant\u00eda estad\u00edstica. La pregunta es si tu API se cae con \u00e9l o lo maneja con elegancia.<\/p>\n\n\n\n<p>Polly \u2014integrado de forma est\u00e1ndar en .NET desde la versi\u00f3n 8\u2014 implementa patrones de resiliencia: reintentos con backoff exponencial, timeouts y circuit breakers.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">\/\/ Opci\u00f3n 1: Pipeline est\u00e1ndar preconfigurado (la manera m\u00e1s r\u00e1pida)\n\/\/ Incluye: reintentos exponenciales + circuit breaker + timeout + hedging\nbuilder.Services.AddHttpClient(\"ExternalAPI\", client =>\n    client.BaseAddress = new Uri(\"https:\/\/api.externa.com\"))\n    .AddStandardResilienceHandler();\n\n\/\/ Opci\u00f3n 2: Pipeline personalizado para control fino\nbuilder.Services.AddHttpClient(\"CriticalService\", client =>\n    client.BaseAddress = new Uri(\"https:\/\/servicio-critico.com\"))\n    .AddResilienceHandler(\"custom\", pipeline =>\n    {\n        \/\/ Timeout total de la operaci\u00f3n\n        pipeline.AddTimeout(TimeSpan.FromSeconds(10));\n\n        \/\/ Reintentos: 3 intentos con backoff exponencial\n        pipeline.AddRetry(new HttpRetryStrategyOptions\n        {\n            MaxRetryAttempts = 3,\n            Delay = TimeSpan.FromMilliseconds(500),\n            BackoffType = DelayBackoffType.Exponential,\n            UseJitter = true, \/\/ Evita thundering herd\n            ShouldHandle = args => args.Outcome switch\n            {\n                { Exception: HttpRequestException } => PredicateResult.True(),\n                { Result.StatusCode: HttpStatusCode.ServiceUnavailable } => PredicateResult.True(),\n                _ => PredicateResult.False()\n            }\n        });\n\n        \/\/ Circuit Breaker: abre despu\u00e9s de 50% de fallos en 30 segundos\n        pipeline.AddCircuitBreaker(new HttpCircuitBreakerStrategyOptions\n        {\n            FailureRatio = 0.5,\n            SamplingDuration = TimeSpan.FromSeconds(30),\n            MinimumThroughput = 10,\n            BreakDuration = TimeSpan.FromSeconds(15)\n        });\n    });<\/code><\/pre>\n\n\n\n<p>El <strong>Circuit Breaker<\/strong> es especialmente importante: cuando un servicio externo falla repetidamente, el circuit breaker \u00ababre\u00bb y deja de intentar llamarlo durante un per\u00edodo, evitando que los timeouts se acumulen y degraden toda tu API.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">10. Feature Flags: deployar sin activar<\/h2>\n\n\n\n<p>Los feature flags cambiaron mi forma de deployar. Antes, cada feature nueva era un riesgo: si algo fallaba en producci\u00f3n, hab\u00eda que hacer rollback, lo cual es lento y estresante. Hoy puedo subir c\u00f3digo a producci\u00f3n con la funcionalidad apagada, activarla para el 5% de los usuarios, monitorear, y si todo va bien, activarla para todos. Sin rollback, sin estr\u00e9s.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">dotnet add package Microsoft.FeatureManagement.AspNetCore<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">builder.Services.AddFeatureManagement();\n\napp.MapGet(\"\/api\/beta-feature\", async (IFeatureManager featureManager) =>\n{\n    if (await featureManager.IsEnabledAsync(\"BetaFeatureX\"))\n        return Results.Ok(\"\u00a1Nueva funcionalidad activada!\");\n\n    return Results.StatusCode(StatusCodes.Status404NotFound);\n});\n\n\/\/ Tambi\u00e9n pod\u00e9s proteger endpoints completos con filtros de acci\u00f3n\napp.MapGet(\"\/api\/new-algorithm\", [FeatureGate(\"NewAlgorithm\")] () =>\n    Results.Ok(RunNewAlgorithm()));<\/code><\/pre>\n\n\n\n<p>Los flags se configuran en <code>appsettings.json<\/code> (para desarrollo) o en <strong>Azure App Configuration<\/strong> (para producci\u00f3n con control en tiempo real sin redeploy):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"json\" class=\"language-json\">{\n  \"FeatureManagement\": {\n    \"BetaFeatureX\": false,\n    \"NewAlgorithm\": {\n      \"EnabledFor\": [\n        {\n          \"Name\": \"Percentage\",\n          \"Parameters\": { \"Value\": 10 }\n        }\n      ]\n    }\n  }\n}<\/code><\/pre>\n\n\n\n<p>Pod\u00e9s activar features para un porcentaje de usuarios, para usuarios espec\u00edficos, por fecha de activaci\u00f3n, o con cualquier l\u00f3gica custom. Ideal para Canary Releases y pruebas A\/B.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">11. Server-Sent Events (SSE): tiempo real sin la complejidad de WebSockets<\/h2>\n\n\n\n<p>WebSockets es la primera opci\u00f3n que se te ocurre para \u00abtiempo real\u00bb, pero tiene overhead de setup y complejidad de manejo de conexiones bidireccionales. Si solo necesit\u00e1s enviar datos del servidor al cliente \u2014notificaciones, progreso de tareas, feeds de datos\u2014 SSE es mucho m\u00e1s simple y funciona sobre HTTP est\u00e1ndar.<\/p>\n\n\n\n<p>En .NET 10, implementarlo con <code>IAsyncEnumerable<\/code> es elegante y eficiente:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">\/\/ Ejemplo 1: Stream simple de notificaciones\napp.MapGet(\"\/api\/notifications\", async IAsyncEnumerable&lt;string&gt; (CancellationToken ct) =>\n{\n    for (int i = 0; i &lt; 5 &amp;&amp; !ct.IsCancellationRequested; i++)\n    {\n        await Task.Delay(1000, ct);\n        yield return $\"data: Notificaci\u00f3n {i + 1}\\n\\n\";\n    }\n});\n\n\/\/ Ejemplo 2: Progreso de una tarea larga\napp.MapPost(\"\/api\/export\", async IAsyncEnumerable&lt;ProgressUpdate&gt; (ExportRequest request, CancellationToken ct) =>\n{\n    var items = await GetItemsToExport(request);\n    int total = items.Count;\n\n    for (int i = 0; i &lt; total &amp;&amp; !ct.IsCancellationRequested; i++)\n    {\n        await ProcessItem(items[i]);\n        yield return new ProgressUpdate\n        {\n            Current = i + 1,\n            Total = total,\n            Percentage = (int)((i + 1.0) \/ total * 100)\n        };\n    }\n});\n\nrecord ProgressUpdate(int Current, int Total, int Percentage);<\/code><\/pre>\n\n\n\n<p>El cliente recibe un flujo continuo de datos sin necesidad de polling. Perfecto para dashboards en tiempo real, barras de progreso de procesos largos, o feeds de eventos de sistema.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">El checklist completo de producci\u00f3n<\/h2>\n\n\n\n<p>Antes de llevar cualquier Web API a producci\u00f3n, repaso esta lista de los 11 componentes que cubrimos en la serie:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>&#x2705; <strong>Health Checks<\/strong> \u2014 Liveness y Readiness configurados<\/li>\n<li>&#x2705; <strong>Exception Handler global<\/strong> \u2014 ProblemDetails para todos los errores<\/li>\n<li>&#x2705; <strong>Validaci\u00f3n<\/strong> \u2014 Endpoint Filters antes de la l\u00f3gica de negocio<\/li>\n<li>&#x2705; <strong>OpenAPI nativo<\/strong> \u2014 Documentaci\u00f3n sin Swashbuckle<\/li>\n<li>&#x2705; <strong>Rate Limiting<\/strong> \u2014 Protecci\u00f3n en endpoints p\u00fablicos<\/li>\n<li>&#x2705; <strong>Output Cache<\/strong> \u2014 En endpoints de lectura costosos<\/li>\n<li>&#x2705; <strong>API Versioning<\/strong> \u2014 Desde el primer endpoint<\/li>\n<li>&#x2705; <strong>OpenTelemetry<\/strong> \u2014 M\u00e9tricas, trazas y logs exportando<\/li>\n<li>&#x2705; <strong>Polly<\/strong> \u2014 Resiliencia en todas las llamadas externas<\/li>\n<li>&#x2705; <strong>Feature Flags<\/strong> \u2014 Para funcionalidades en desarrollo activo<\/li>\n<li>&#x2705; <strong>SSE<\/strong> \u2014 En lugar de polling para actualizaciones en tiempo real<\/li>\n<\/ul>\n\n\n\n<p>No hace falta implementarlos todos desde el d\u00eda uno, pero s\u00ed conviene tenerlos en el radar desde que empez\u00e1s. Cuanto m\u00e1s temprano los incorpor\u00e9s, menos dolores de cabeza cuando la API escale.<\/p>\n\n\n\n<p>\u00bfHay alg\u00fan componente que uses habitualmente y no est\u00e9 en la lista? Dejamelo en los comentarios.<\/p>\n\n\n\n<p><em>\u2190 <a href=\"\/arquitectura-web-api-dotnet-10-parte-2\">Parte 2: Rate Limiting, Output Cache y API Versioning<\/a><\/em><\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>OpenTelemetry, Polly, Feature Flags y Server-Sent Events: los componentes avanzados que llevan una Web API con .NET 10 de funcional a lista para producci\u00f3n de verdad.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1,202],"tags":[38,304,321,245,300,39,316,242,18,294,317,305,313,266,324,310,307,315,65,318,314,319,320,323,322],"class_list":["post-1276","post","type-post","status-publish","format-standard","hentry","category-blog","category-dotnet","tag-net","tag-aot","tag-api-versioning","tag-arquitectura","tag-async","tag-c","tag-caching","tag-devops","tag-dotnet","tag-dotnet10","tag-feature-flags","tag-gc","tag-health-checks","tag-microservicios","tag-middleware","tag-minimal-api","tag-openapi","tag-opentelemetry","tag-performance","tag-polly","tag-rate-limiting","tag-resiliency","tag-sse","tag-validation","tag-web-api"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real &#183; devops Mauro Bernal<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real &#183; devops Mauro Bernal\" \/>\n<meta property=\"og:description\" content=\"OpenTelemetry, Polly, Feature Flags y Server-Sent Events: los componentes avanzados que llevan una Web API con .NET 10 de funcional a lista para producci\u00f3n de verdad.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/\" \/>\n<meta property=\"og:site_name\" content=\"devops Mauro Bernal\" \/>\n<meta property=\"article:published_time\" content=\"2026-03-12T12:29:16+00:00\" \/>\n<meta name=\"author\" content=\"Mauro Bernal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@_maurobernal\" \/>\n<meta name=\"twitter:site\" content=\"@_maurobernal\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mauro Bernal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/\"},\"author\":{\"name\":\"Mauro Bernal\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\"},\"headline\":\"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real\",\"datePublished\":\"2026-03-12T12:29:16+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/\"},\"wordCount\":717,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\"},\"keywords\":[\".NET\",\"aot\",\"api-versioning\",\"arquitectura\",\"async\",\"c#\",\"caching\",\"devops\",\"dotnet\",\"dotnet10\",\"feature-flags\",\"gc\",\"health-checks\",\"microservicios\",\"middleware\",\"minimal-api\",\"openapi\",\"opentelemetry\",\"performance\",\"polly\",\"rate-limiting\",\"resiliency\",\"sse\",\"validation\",\"web-api\"],\"articleSection\":[\"Blog\",\"DotNet\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/\",\"url\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/\",\"name\":\"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real &#183; devops Mauro Bernal\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#website\"},\"datePublished\":\"2026-03-12T12:29:16+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-3\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/\",\"name\":\"devops Mauro Bernal\",\"description\":\"Cuando tu trabajo es hacer que las cosas funcionen bien...\",\"publisher\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\",\"name\":\"Mauro Bernal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/i0.wp.com\\\/maurobernal.com.ar\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/logo-maurobernal.png?fit=1740%2C1740&ssl=1\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/maurobernal.com.ar\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/logo-maurobernal.png?fit=1740%2C1740&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/maurobernal.com.ar\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/logo-maurobernal.png?fit=1740%2C1740&ssl=1\",\"width\":1740,\"height\":1740,\"caption\":\"Mauro Bernal\"},\"logo\":{\"@id\":\"https:\\\/\\\/i0.wp.com\\\/maurobernal.com.ar\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/logo-maurobernal.png?fit=1740%2C1740&ssl=1\"},\"description\":\"Desarrollo de Sistemas en .Net, IT Callcenters, DBA de SQL Server, Mikrotik, Pentest y T\u00e9cnico consultor de Sistemas Bejerman\",\"sameAs\":[\"https:\\\/\\\/maurobernal.com.ar\",\"https:\\\/\\\/x.com\\\/_maurobernal\",\"https:\\\/\\\/youtube.com\\\/maurobernal\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real &#183; devops Mauro Bernal","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/","og_locale":"es_ES","og_type":"article","og_title":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real &#183; devops Mauro Bernal","og_description":"OpenTelemetry, Polly, Feature Flags y Server-Sent Events: los componentes avanzados que llevan una Web API con .NET 10 de funcional a lista para producci\u00f3n de verdad.","og_url":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/","og_site_name":"devops Mauro Bernal","article_published_time":"2026-03-12T12:29:16+00:00","author":"Mauro Bernal","twitter_card":"summary_large_image","twitter_creator":"@_maurobernal","twitter_site":"@_maurobernal","twitter_misc":{"Escrito por":"Mauro Bernal","Tiempo de lectura":"5 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/#article","isPartOf":{"@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/"},"author":{"name":"Mauro Bernal","@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283"},"headline":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real","datePublished":"2026-03-12T12:29:16+00:00","mainEntityOfPage":{"@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/"},"wordCount":717,"commentCount":0,"publisher":{"@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283"},"keywords":[".NET","aot","api-versioning","arquitectura","async","c#","caching","devops","dotnet","dotnet10","feature-flags","gc","health-checks","microservicios","middleware","minimal-api","openapi","opentelemetry","performance","polly","rate-limiting","resiliency","sse","validation","web-api"],"articleSection":["Blog","DotNet"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/","url":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/","name":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real &#183; devops Mauro Bernal","isPartOf":{"@id":"https:\/\/maurobernal.com.ar\/blog\/#website"},"datePublished":"2026-03-12T12:29:16+00:00","breadcrumb":{"@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-3\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/maurobernal.com.ar\/blog\/"},{"@type":"ListItem","position":2,"name":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 3: Observabilidad, Resiliencia y Tiempo Real"}]},{"@type":"WebSite","@id":"https:\/\/maurobernal.com.ar\/blog\/#website","url":"https:\/\/maurobernal.com.ar\/blog\/","name":"devops Mauro Bernal","description":"Cuando tu trabajo es hacer que las cosas funcionen bien...","publisher":{"@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/maurobernal.com.ar\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":["Person","Organization"],"@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283","name":"Mauro Bernal","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/i0.wp.com\/maurobernal.com.ar\/blog\/wp-content\/uploads\/2023\/07\/logo-maurobernal.png?fit=1740%2C1740&ssl=1","url":"https:\/\/i0.wp.com\/maurobernal.com.ar\/blog\/wp-content\/uploads\/2023\/07\/logo-maurobernal.png?fit=1740%2C1740&ssl=1","contentUrl":"https:\/\/i0.wp.com\/maurobernal.com.ar\/blog\/wp-content\/uploads\/2023\/07\/logo-maurobernal.png?fit=1740%2C1740&ssl=1","width":1740,"height":1740,"caption":"Mauro Bernal"},"logo":{"@id":"https:\/\/i0.wp.com\/maurobernal.com.ar\/blog\/wp-content\/uploads\/2023\/07\/logo-maurobernal.png?fit=1740%2C1740&ssl=1"},"description":"Desarrollo de Sistemas en .Net, IT Callcenters, DBA de SQL Server, Mikrotik, Pentest y T\u00e9cnico consultor de Sistemas Bejerman","sameAs":["https:\/\/maurobernal.com.ar","https:\/\/x.com\/_maurobernal","https:\/\/youtube.com\/maurobernal"]}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts\/1276","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/comments?post=1276"}],"version-history":[{"count":1,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts\/1276\/revisions"}],"predecessor-version":[{"id":1279,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts\/1276\/revisions\/1279"}],"wp:attachment":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/media?parent=1276"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/categories?post=1276"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/tags?post=1276"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}