- September 22, 2025
- linkzeeshan.ayyub
Faster releases • Lower cost • Stronger security
Why .NET 9/10 Matters for Businesses
Got it—here’s a compact .NET 9/10–style Minimal API snippet that demonstrates the business benefits you’re highlighting:
-
Performance: Output caching + Redis cache, async EF Core, response compression
-
Security: JWT auth + rate limiting
-
Scalability/Reliability: Polly retries/circuit breaker on outbound calls, health checks
Program.cs
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.RateLimiting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using Polly;
using Polly.Extensions.Http;
using System.Net;
using System.Threading.RateLimiting;
var builder = WebApplication.CreateBuilder(args);
// ===== Services =====
builder.Services.AddResponseCompression(); // Perf
builder.Services.AddOutputCache(); // Perf
builder.Services.AddStackExchangeRedisCache(o => // Perf / Cost
o.Configuration = builder.Configuration["REDIS_CONN"]);
builder.Services.AddDbContext(o => // Perf
o.UseNpgsql(builder.Configuration["POSTGRES_CONN"])
.UseQuerySplittingBehavior(QuerySplittingBehavior.SplitQuery));
builder.Services.AddHealthChecks() // Reliability
.AddNpgSql(builder.Configuration["POSTGRES_CONN"])
.AddRedis(builder.Configuration["REDIS_CONN"]!);
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(); // Security
builder.Services.AddAuthorization();
builder.Services.AddRateLimiter(o => // Security / Cost protection
{
o.GlobalLimiter = PartitionedRateLimiter.Create(ctx =>
RateLimitPartition.GetFixedWindowLimiter(
partitionKey: ctx.User?.Identity?.Name ?? ctx.Connection.RemoteIpAddress?.ToString() ?? "anon",
factory: _ => new FixedWindowRateLimiterOptions
{
PermitLimit = 100, Window = TimeSpan.FromMinutes(1),
QueueProcessingOrder = QueueProcessingOrder.OldestFirst,
QueueLimit = 50
}));
});
builder.Services.AddHttpClient("catalog", c => // Reliability / Scale
{
c.BaseAddress = new Uri(builder.Configuration["CATALOG_API"]!);
})
.AddPolicyHandler(HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(r => r.StatusCode == HttpStatusCode.TooManyRequests)
.WaitAndRetryAsync(3, attempt => TimeSpan.FromMilliseconds(200 * attempt)))
.AddPolicyHandler(HttpPolicyExtensions
.HandleTransientHttpError()
.CircuitBreakerAsync(5, TimeSpan.FromSeconds(30)));
builder.Services.AddScoped();
var app = builder.Build();
// ===== Pipeline =====
app.UseResponseCompression();
app.UseOutputCache();
app.UseRateLimiter();
app.UseAuthentication();
app.UseAuthorization();
app.MapHealthChecks("/health");
// Example endpoint: Users -> API layer -> Services/DB
app.MapGet("/api/products", async (ProductService svc) =>
{
var products = await svc.GetProductsCachedAsync();
return Results.Ok(products);
})
.RequireAuthorization() // Security
.CacheOutput(p => p.Expire(TimeSpan.FromSeconds(60))); // Perf
app.Run();
// ===== EF Core =====
public class AppDb : DbContext
{
public AppDb(DbContextOptions opt) : base(opt) { }
public DbSet Products => Set();
}
public record Product(int Id, string Name, decimal Price);
ProductService.cs
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
public class ProductService
{
private readonly AppDb _db;
private readonly IDistributedCache _cache;
private static readonly JsonSerializerOptions _json = new(JsonSerializerDefaults.Web);
public ProductService(AppDb db, IDistributedCache cache)
{
_db = db; _cache = cache;
}
public async Task> GetProductsCachedAsync()
{
const string key = "products:list:v1";
var cached = await _cache.GetStringAsync(key);
if (cached is not null)
return JsonSerializer.Deserialize>(cached, _json)!;
// Efficient EF Core query (perf-friendly defaults)
var products = await _db.Products
.AsNoTracking()
.OrderBy(p => p.Name)
.ToListAsync();
await _cache.SetStringAsync(
key,
JsonSerializer.Serialize(products, _json),
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5)
});
return products;
}
}
Optional: ultra-small Dockerfile (for cost/scalability)
# Build stage FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build WORKDIR /src COPY . . RUN dotnet publish -c Release -o /app # Runtime stage FROM mcr.microsoft.com/dotnet/aspnet:9.0 AS runtime WORKDIR /app COPY --from=build /app . ENV ASPNETCORE_URLS=http://+:8080 EXPOSE 8080 ENTRYPOINT ["dotnet", "YourApp.dll"]
How this maps to your diagram & benefits
-
Users → API layer → Services:
/api/productsendpoint sits in the API layer; data comes from Services/DB with Redis caching. -
Cost reduction: Redis caching + compression + rate limiting reduce CPU/IO and protect infra.
-
Scalability/Reliability: Polly policies, health checks, containerization.
-
Security: JWT auth + rate limiting.