{"id":1275,"date":"2026-03-12T09:29:14","date_gmt":"2026-03-12T12:29:14","guid":{"rendered":"https:\/\/maurobernal.com.ar\/blog\/?p=1275"},"modified":"2026-03-12T09:29:14","modified_gmt":"2026-03-12T12:29:14","slug":"arquitectura-web-api-dotnet-10-parte-2","status":"publish","type":"post","link":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/","title":{"rendered":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 2: Performance y Escalabilidad"},"content":{"rendered":"\n<p>Esta es la segunda 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> cubrimos los fundamentos: Health Checks, Exception Handling, Validaci\u00f3n y OpenAPI nativo. Ahora le toca el turno a los componentes que marcan la diferencia cuando tu API empieza a recibir carga real.<\/p>\n\n\n\n<p>Estos tres los ignor\u00e9 durante demasiado tiempo, hasta que los problemas aparecieron solos en producci\u00f3n.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">5. Rate Limiting: proteg\u00e9 tu API del abuso<\/h2>\n\n\n\n<p>Una API p\u00fablica sin rate limiting es un blanco f\u00e1cil. Me toc\u00f3 ver picos de miles de requests por minuto desde una sola IP dejando el servidor de rodillas. Desde .NET 7 el middleware de rate limiting viene integrado en el framework, y en .NET 10 est\u00e1 completamente maduro.<\/p>\n\n\n\n<p>.NET ofrece cuatro estrategias distintas seg\u00fan el caso de uso:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Fixed Window:<\/strong> X peticiones por ventana de tiempo fija<\/li>\n<li><strong>Sliding Window:<\/strong> igual pero la ventana se mueve (m\u00e1s preciso)<\/li>\n<li><strong>Token Bucket:<\/strong> permite bursts controlados<\/li>\n<li><strong>Concurrency:<\/strong> limita las peticiones simult\u00e1neas, no el rate<\/li>\n<\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">builder.Services.AddRateLimiter(options =>\n{\n    \/\/ Pol\u00edtica general: 100 requests por minuto por IP\n    options.AddFixedWindowLimiter(\"General\", opt =>\n    {\n        opt.Window = TimeSpan.FromMinutes(1);\n        opt.PermitLimit = 100;\n        opt.QueueProcessingOrder = QueueProcessingOrder.OldestFirst;\n        opt.QueueLimit = 10; \/\/ Cu\u00e1ntas requests pueden esperar en cola\n    });\n\n    \/\/ Pol\u00edtica estricta para endpoints sensibles\n    options.AddSlidingWindowLimiter(\"Strict\", opt =>\n    {\n        opt.Window = TimeSpan.FromMinutes(1);\n        opt.SegmentsPerWindow = 6; \/\/ Segmentos de 10 segundos\n        opt.PermitLimit = 20;\n    });\n\n    \/\/ Respuesta personalizada cuando se supera el l\u00edmite\n    options.OnRejected = async (context, cancellationToken) =>\n    {\n        context.HttpContext.Response.StatusCode = StatusCodes.Status429TooManyRequests;\n        await context.HttpContext.Response.WriteAsJsonAsync(\n            new ProblemDetails { Title = \"Too Many Requests\", Status = 429 },\n            cancellationToken);\n    };\n});\n\nvar app = builder.Build();\napp.UseRateLimiter();\n\n\/\/ Aplicar a endpoints espec\u00edficos\napp.MapGet(\"\/api\/data\", () => \"Datos\")\n   .RequireRateLimiting(\"General\");\n\napp.MapPost(\"\/api\/auth\/login\", (LoginDto dto) => Results.Ok())\n   .RequireRateLimiting(\"Strict\");<\/code><\/pre>\n\n\n\n<p>Para APIs que manejan usuarios autenticados, pod\u00e9s segmentar el rate limiting por user ID en lugar de IP, as\u00ed los usuarios leg\u00edtimos no se ven afectados por el comportamiento de otros.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">6. Output Cache: no calcules lo mismo dos veces<\/h2>\n\n\n\n<p>En un proyecto de reportes que ten\u00eda consultas de 2 segundos contra SQL Server, implementar Output Caching llev\u00f3 el tiempo de respuesta promedio a menos de 10ms. Sin tocar una sola l\u00ednea de l\u00f3gica de negocio.<\/p>\n\n\n\n<p>Para endpoints que devuelven datos que no cambian constantemente, el Output Cache guarda la respuesta completa en memoria (o Redis) y la sirve directamente sin ejecutar nada de la l\u00f3gica de negocio.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">builder.Services.AddOutputCache(options =>\n{\n    \/\/ Pol\u00edtica base: cache de 60 segundos\n    options.AddBasePolicy(builder => builder.Expire(TimeSpan.FromSeconds(60)));\n\n    \/\/ Pol\u00edtica nombrada para datos de referencia\n    options.AddPolicy(\"ReferenceData\", builder =>\n        builder.Expire(TimeSpan.FromMinutes(10))\n               .Tag(\"reference\")); \/\/ Tag para invalidaci\u00f3n selectiva\n});\n\nvar app = builder.Build();\napp.UseOutputCache();\n\n\/\/ Cache por 10 segundos (override de la pol\u00edtica base)\napp.MapGet(\"\/api\/stats\", () => GetExpensiveStats())\n   .CacheOutput(c => c.Expire(TimeSpan.FromSeconds(10)));\n\n\/\/ Usando pol\u00edtica nombrada\napp.MapGet(\"\/api\/products\", () => GetProducts())\n   .CacheOutput(\"ReferenceData\");\n\n\/\/ Invalidar el cache cuando cambian los datos\napp.MapPost(\"\/api\/products\", async (ProductDto product, IOutputCacheStore cache) =>\n{\n    await SaveProduct(product);\n    await cache.EvictByTagAsync(\"reference\", CancellationToken.None); \/\/ Invalida el cache\n    return Results.Created($\"\/api\/products\/{product.Id}\", product);\n});<\/code><\/pre>\n\n\n\n<p>La invalidaci\u00f3n por tags es la clave para usar Output Cache sin miedo a servir datos stale. Cuando mut\u00e1s datos, invalid\u00e1s el tag correspondiente y la pr\u00f3xima request regenera el cache.<\/p>\n\n\n\n<p>Para ambientes distribuidos (m\u00faltiples instancias), pod\u00e9s configurar Redis como backing store con <code>AddStackExchangeRedisOutputCache()<\/code>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">7. API Versioning: cambiar sin romper a tus clientes<\/h2>\n\n\n\n<p>Esta es una de las lecciones m\u00e1s caras que aprend\u00ed: si tu API tiene clientes externos y no versiona desde el principio, el d\u00eda que necesit\u00e9s hacer un cambio incompatible vas a tener un problema enorme. Agregarle versionado a una API ya desplegada es doloroso. Hacerlo desde el inicio es trivial.<\/p>\n\n\n\n<p>En Minimal APIs el versionado se maneja mediante <strong>Version Sets<\/strong>. Primero instal\u00e1 el paquete <code>Asp.Versioning.Http<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">dotnet add package Asp.Versioning.Http<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"csharp\" class=\"language-csharp\">\/\/ Program.cs\nbuilder.Services.AddApiVersioning(options =>\n{\n    options.DefaultApiVersion = new ApiVersion(1, 0);\n    options.AssumeDefaultVersionWhenUnspecified = true;\n    options.ReportApiVersions = true; \/\/ Devuelve las versiones disponibles en headers\n});\n\nvar app = builder.Build();\n\nvar apiVersionSet = app.NewApiVersionSet()\n    .HasApiVersion(new ApiVersion(1, 0))\n    .HasApiVersion(new ApiVersion(2, 0))\n    .ReportApiVersions()\n    .Build();\n\n\/\/ V1: respuesta simple\napp.MapGet(\"\/api\/v{version:apiVersion}\/users\", () =>\n    new[] { new { Id = 1, Name = \"Juan\" } })\n   .WithApiVersionSet(apiVersionSet)\n   .MapToApiVersion(1, 0);\n\n\/\/ V2: respuesta enriquecida con datos extra\napp.MapGet(\"\/api\/v{version:apiVersion}\/users\", () =>\n    new[] { new { Id = 1, Name = \"Juan\", Email = \"juan@ejemplo.com\", Role = \"Admin\" } })\n   .WithApiVersionSet(apiVersionSet)\n   .MapToApiVersion(2, 0);<\/code><\/pre>\n\n\n\n<p>Los clientes existentes siguen usando <code>\/api\/v1\/users<\/code> sin ning\u00fan cambio. Los nuevos pueden adoptar <code>\/api\/v2\/users<\/code> con el formato enriquecido. Convivencia perfecta.<\/p>\n\n\n\n<p>Adem\u00e1s del versionado por URL, pod\u00e9s usar <strong>query string<\/strong> (<code>?api-version=2.0<\/code>) o <strong>header<\/strong> (<code>X-API-Version: 2.0<\/code>) seg\u00fan las necesidades de tus clientes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Resumen de la Parte 2<\/h2>\n\n\n\n<p>Tres componentes que hacen la diferencia cuando la API escala:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>&#x2705; <strong>Rate Limiting<\/strong> \u2192 protecci\u00f3n contra abuso, con estrategias flexibles por caso de uso<\/li>\n<li>&#x2705; <strong>Output Cache<\/strong> \u2192 performance brutal en endpoints de lectura, con invalidaci\u00f3n inteligente<\/li>\n<li>&#x2705; <strong>API Versioning<\/strong> \u2192 libertad para evolucionar sin romper contratos existentes<\/li>\n<\/ul>\n\n\n\n<p>En la <a href=\"\/arquitectura-web-api-dotnet-10-parte-3\">Parte 3<\/a> cerramos la serie con los componentes m\u00e1s avanzados: <strong>OpenTelemetry, Polly, Feature Flags y Server-Sent Events<\/strong>.<\/p>\n\n","protected":false},"excerpt":{"rendered":"<p>Rate Limiting, Output Cache con invalidaci\u00f3n por tags y API Versioning: los tres componentes que marcan la diferencia cuando tu Web API con .NET 10 empieza a recibir carga real.<\/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-1275","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 2: Performance y Escalabilidad &#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-2\/\" \/>\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 2: Performance y Escalabilidad &#183; devops Mauro Bernal\" \/>\n<meta property=\"og:description\" content=\"Rate Limiting, Output Cache con invalidaci\u00f3n por tags y API Versioning: los tres componentes que marcan la diferencia cuando tu Web API con .NET 10 empieza a recibir carga real.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/\" \/>\n<meta property=\"og:site_name\" content=\"devops Mauro Bernal\" \/>\n<meta property=\"article:published_time\" content=\"2026-03-12T12:29:14+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=\"4 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-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-2\\\/\"},\"author\":{\"name\":\"Mauro Bernal\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\"},\"headline\":\"Arquitectura de Web APIs en .NET 10 \u2014 Parte 2: Performance y Escalabilidad\",\"datePublished\":\"2026-03-12T12:29:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-2\\\/\"},\"wordCount\":523,\"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-2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-2\\\/\",\"url\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-2\\\/\",\"name\":\"Arquitectura de Web APIs en .NET 10 \u2014 Parte 2: Performance y Escalabilidad &#183; devops Mauro Bernal\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#website\"},\"datePublished\":\"2026-03-12T12:29:14+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-2\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-2\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/arquitectura-web-api-dotnet-10-parte-2\\\/#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 2: Performance y Escalabilidad\"}]},{\"@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 2: Performance y Escalabilidad &#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-2\/","og_locale":"es_ES","og_type":"article","og_title":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 2: Performance y Escalabilidad &#183; devops Mauro Bernal","og_description":"Rate Limiting, Output Cache con invalidaci\u00f3n por tags y API Versioning: los tres componentes que marcan la diferencia cuando tu Web API con .NET 10 empieza a recibir carga real.","og_url":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/","og_site_name":"devops Mauro Bernal","article_published_time":"2026-03-12T12:29:14+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":"4 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/#article","isPartOf":{"@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/"},"author":{"name":"Mauro Bernal","@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283"},"headline":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 2: Performance y Escalabilidad","datePublished":"2026-03-12T12:29:14+00:00","mainEntityOfPage":{"@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/"},"wordCount":523,"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-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/","url":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/","name":"Arquitectura de Web APIs en .NET 10 \u2014 Parte 2: Performance y Escalabilidad &#183; devops Mauro Bernal","isPartOf":{"@id":"https:\/\/maurobernal.com.ar\/blog\/#website"},"datePublished":"2026-03-12T12:29:14+00:00","breadcrumb":{"@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/maurobernal.com.ar\/blog\/arquitectura-web-api-dotnet-10-parte-2\/#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 2: Performance y Escalabilidad"}]},{"@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\/1275","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=1275"}],"version-history":[{"count":1,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts\/1275\/revisions"}],"predecessor-version":[{"id":1278,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts\/1275\/revisions\/1278"}],"wp:attachment":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/media?parent=1275"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/categories?post=1275"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/tags?post=1275"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}