El 10 de noviembre de 2026 salió .NET 11 y, ese mismo día, .NET 8 y .NET 9 se quedaron sin soporte. Si tienes servicios en cualquiera de las dos, el calendario ya no da margen: o saltas a .NET 10 (LTS) o a .NET 11, una versión STS con dos años de soporte que además deja de arrancar en procesadores x86 anteriores a x86-64-v2.
La versión trae C# 15, async gestionado por el propio runtime (en preview), un SDK más pequeño y más rápido en la CLI y un puñado de cambios de comportamiento que, en un servicio web, se notan más que las novedades.
Lo que gana un servicio en producción
Async nativo del runtime. Es el cambio de fondo más grande. En lugar de que el compilador genere una máquina de estados por cada método async, el runtime gestiona la suspensión y la reanudación. Sigue en preview y se activa por proyecto con <Features>runtime-async=on</Features>, ya sin EnablePreviewFeatures. Lo interesante es que las propias librerías del runtime ya vienen compiladas así, de modo que Microsoft lo está validando a escala. Lo primero que vas a ver son las trazas en vivo: en el ejemplo de la documentación, una cadena de tres métodos async pasa de 13 marcos de pila a 5, sin la infraestructura de AsyncMethodBuilderCore en medio. Para un profiler o para un volcado durante un incidente, eso es tiempo de diagnóstico.
Un JIT que hace menos trabajo inútil. Elimina más comprobaciones de límites (i + cns < len, values[^1], el primer elemento tras comprobar que un Span no está vacío), desvirtualiza métodos virtuales genéricos y pliega comparaciones de cadenas constantes tras el inlining. En ReadyToRun, Comparer<T>.Default y EqualityComparer<T>.Default se especializan en la imagen y Microsoft mide hasta 20 veces más rendimiento en colecciones que dependen del comparador por defecto.
Detalles de operación que se agradecen. El runtime ya arranca en máquinas con más de 1.024 CPU lógicas (antes fallaba al inicializar), lee bien los límites de memoria de cgroup v2 en la raíz de la jerarquía y Guid.NewGuid() usa getrandom() en Linux, con un 12 % más de rendimiento. Además, el informe de fallos en proceso llega a Linux y macOS: con DOTNET_EnableCrashReport=1 el proceso escribe la pila administrada y la lista de módulos antes de morir.
SDK y CLI. El host de la CLI compilado con Native AOT viene activado por defecto y las herramientas como dotnet ef se ahorran los 600–700 ms de arranque de la CLI administrada. El servidor de MSBuild queda caliente entre invocaciones. En Linux x64, el tarball del SDK baja de 230 a 189 MB y las imágenes de contenedor, entre un 8 y un 17 %. Y dos novedades para la cadena de suministro: imágenes de contenedor reproducibles con SOURCE_DATE_EPOCH y una antigüedad mínima de publicación para los paquetes de NuGet.
# Same inputs, same image digest
dotnet publish /t:PublishContainer \
-p:ContainerRegistry=registry.example.com \
-p:SOURCE_DATE_EPOCH="$(git log -1 --pretty=%ct)"
# Ignore package versions published less than 24 hours ago
dotnet nuget add source https://api.nuget.org/v3/index.json --name public \
--min-publish-age-hours 24 --configfile nuget.configLa antigüedad mínima la aplican dotnet package add y dotnet package update al elegir versión; un restore normal solo la hace cumplir en referencias flotantes, donde falla con NU1020.
En el lenguaje, C# 15 trae tipos unión, jerarquías cerradas, argumentos en las expresiones de colección y break/continue con etiqueta. En librerías, Zstandard en System.IO.Compression, FullJoin en LINQ y soporte de uniones en System.Text.Json. ASP.NET Core genera OpenAPI 3.2 por defecto.
Lo que se puede romper
El cambio con más riesgo no está en el código, sino en el hardware. La base mínima en x86/x64 pasa de x86-64-v1 a x86-64-v2 en todos los sistemas (exige SSE4.2, POPCNT y CX16), y en Windows sobre Arm64 se exige LSE. En una CPU que no cumpla, la aplicación no arranca y muestra The current CPU is missing one or more of the baseline instruction sets. Microsoft recuerda que los últimos procesadores sin esas instrucciones dejaron de tener soporte de Intel y AMD hacia 2013, pero en virtualización vieja o con CPU emuladas puede aparecer.
En un servicio con ASP.NET Core o el host genérico, estos cambios de comportamiento son los que yo revisaría primero:
IHost.RunAsyncyIHost.StopAsynclanzan una excepción si falla unBackgroundService. Si tu proceso seguía vivo con un worker caído, ahora se enterará quien lo arranca.- Una cadena vacía en un proveedor de configuración posterior sobrescribe a los anteriores. Una variable de entorno vacía puede anular el valor de
appsettings.json. - Los mutex con nombre son de ámbito de usuario por defecto en Unix, lo que cambia la coordinación entre procesos de usuarios distintos.
SslStreamen servidor ya no descarga certificados intermedios por AIA por defecto. Si tu servidor TLS no envía la cadena completa, aparecerán errores de validación.- Las métricas de
HttpClientde alta cardinalidad pasan a contadores observables: revisa tus dashboards si las consumes por OpenTelemetry. - La lectura de ZIP valida el CRC32 y la de TAR, las sumas de control de las cabeceras: los archivos corruptos que antes pasaban ahora fallan.
Si usabas las variables DOTNET_RuntimeAsync o UNSUPPORTED_RuntimeAsync para probar el async del runtime, han desaparecido; para desactivarlo por proyecto se usa <UseRuntimeAsync>false</UseRuntimeAsync>.
Cómo actualizar a .NET 11
El SDK es el 11.0.100 y el runtime, el 11.0.0. Con el script oficial:
curl -sSL https://dot.net/v1/dotnet-install.sh -o dotnet-install.sh
chmod +x dotnet-install.sh
./dotnet-install.sh --channel 11.0En contenedores, las imágenes ya están en el registro de Microsoft con las etiquetas 11.0, 11.0-alpine y 11.0-azurelinux3.0, entre otras:
FROM mcr.microsoft.com/dotnet/sdk:11.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /app
FROM mcr.microsoft.com/dotnet/aspnet:11.0
WORKDIR /app
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyService.dll"]En el proyecto, el cambio mínimo es <TargetFramework>net11.0</TargetFramework> y, si fijas el SDK con global.json, la versión 11.0.100. En Windows hace falta un Visual Studio 2026 actualizado o VS Code con C# Dev Kit.
.NET 10 LTS o .NET 11 STS
Para quien sale de .NET 8 o 9 con prisa, la decisión es esta. .NET 10 es LTS y sigue con soporte; .NET 11 tiene dos años. Si tu equipo actualiza una vez cada mucho, .NET 10 es la apuesta tranquila. Si ya ibas a pasar por los cambios de comportamiento de arriba y quieres el JIT nuevo, el SDK más ligero y las imágenes reproducibles, .NET 11 compensa, sabiendo que dentro de dos años tocará otro salto.
Checklist antes de producción
- Comprueba que tus nodos (y las CPU que expone tu hipervisor) cumplen x86-64-v2, o LSE en Windows Arm64.
- Compila con
net11.0y revisa los avisos nuevos de obsolescencia (SYSLIB). - Repasa la configuración: valores vacíos en variables de entorno y en proveedores encadenados.
- Provoca a propósito el fallo de un
BackgroundServiceen staging y mira cómo termina el proceso. - Si tu servidor termina TLS con
SslStreamo Kestrel, confirma que envía la cadena de certificados completa. - Compara tus métricas de
HttpClienty tus dashboards antes y después. - Mide latencia y memoria con carga real antes de activar
runtime-async=on, y hazlo primero en un servicio no crítico.
Fuentes
- Announcing .NET 11, blog de .NET, 10 de noviembre de 2026.
- What's new in .NET 11 runtime, Microsoft Learn.
- What's new in the SDK and tooling for .NET 11, Microsoft Learn.
- Breaking changes in .NET 11, Microsoft Learn.