Why .NET, still
I started on ASP.NET 4.0 in 2012 building order-to-delivery portals for Masafi in the UAE. Fourteen years later, the same platform — radically modernized — runs the EV charging systems I architect today. That continuity is the point: .NET evolved from a Windows-only framework into a fast, cross-platform, open-source runtime without ever forcing its ecosystem to start over. Few platforms can carry a codebase and a career that far.
The evolution I lived through
- 2012–2016: ASP.NET WebForms and MVC, SQL Server, jQuery — enterprise portals for the Gulf market (Masafi, Zaika, Shine Eleven).
- 2016–2019: ASP.NET MVC at scale — leading teams, introducing CI/CD, reusable component libraries.
- 2019–2023: .NET Core microservices — vending IoT platforms handling 1M+ daily interactions.
- 2023–now: .NET 8 — OCPI/OCPP/Beckn-compliant EV charging services with API gateways, MQTT, and RabbitMQ.
What .NET does better than anything else
- Long-term maintainability: strong typing, one language (C#) across services, jobs, and tooling — critical when platforms live for a decade.
- Performance without exotic engineering: Kestrel and async/await handle tens of thousands of concurrent charger connections on modest hardware.
- First-class Azure integration: identity, Key Vault, App Insights, and DevOps pipelines work out of the box.
- Hiring and continuity: in the Indian enterprise market, strong .NET teams are buildable — an underrated architecture decision.
Production lessons
- Upgrade continuously, not eventually — a service stuck on .NET Core 3.1 becomes a security liability; small yearly hops beat big rewrites.
- Keep controllers thin and domain logic in plain C# classes — frameworks change, business rules survive.
- Async all the way down: one blocking call in a charger-facing endpoint cascades under load.
- Health checks and structured logging (Serilog + App Insights) are not optional at 99% uptime targets.
Worked example: a resilient background worker
The shape of half my platform code — a hosted service that sweeps expired charging sessions, with cancellation, logging, and no blocked threads:
public sealed class SessionExpirySweeper : BackgroundService
{
private readonly ISessionStore _sessions;
private readonly ILogger<SessionExpirySweeper> _log;
public SessionExpirySweeper(ISessionStore sessions, ILogger<SessionExpirySweeper> log)
=> (_sessions, _log) = (sessions, log);
protected override async Task ExecuteAsync(CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
var expired = await _sessions.FindExpiredAsync(TimeSpan.FromMinutes(30), ct);
foreach (var s in expired)
{
await _sessions.CloseAsync(s.Id, SessionCloseReason.Timeout, ct);
_log.LogWarning("Session {SessionId} closed by expiry sweep", s.Id);
}
await Task.Delay(TimeSpan.FromMinutes(1), ct);
}
}
}
Registered with services.AddHostedService<SessionExpirySweeper>() — it deploys, scales, and ships logs with the API it supports.
FAQ
Yes — for enterprise systems with long lifespans, regulated integrations, and mixed cloud/on-prem needs, .NET 8+ offers performance comparable to Go with a far deeper enterprise ecosystem.
.NET Framework (4.x) is legacy Windows-only; modern .NET (Core, 5–8+) is cross-platform and where all investment goes. All my current platforms run modern .NET on Linux containers.
MySQL or SQL Server for data, RabbitMQ and MQTT for messaging, Angular for admin frontends, Docker for packaging, and Azure DevOps for delivery.