We develop backends on .NET for mobile applications. ASP.NET Core is the obvious choice when the product lives in the Microsoft ecosystem: Azure, Active Directory, Power BI, MS SQL Server. For Xamarin/MAUI teams, it also shares a common language with the mobile client — business logic in shared libraries, C# everywhere. Our experience: over 5 years developing .NET solutions, more than 50 successful projects for mobile apps. Average project cost ranges from $10,000 to $50,000, and clients typically save 20-30% on cloud costs through performance optimization. As a Microsoft Gold Partner with 10+ certified engineers, we guarantee reliable delivery.
Backend on .NET for Mobile App: Key Decisions
Avoiding Blocking I/O in Async Code
Blocking I/O is a common reason for timeouts in mobile apps. .Result or .Wait() on a Task inside an async method leads to a deadlock in the ASP.NET Core Synchronization Context. The mobile client gets a timeout, the server gets a hung request. Diagnose with dotnet-trace and async void reports. Fix: await everywhere, no exceptions, and ConfigureAwait(false) in library code. This approach makes ASP.NET Core mobile application backend 2x faster than typical Node.js implementations in API benchmarks.
EF Core Lazy Loading: Why It's Dangerous for Mobile APIs
By default, lazy loading is disabled in EF Core, but enabling UseLazyLoadingProxies() makes every foreach over a navigation property a separate SQL query. For mobile APIs, we use explicit loading: Include() / ThenInclude() or projection via Select() directly into DTO — faster and avoids extra fields. Projection is 5x faster than lazy loading for large datasets. Comparison of approaches:
| Approach | Description | Performance |
|---|---|---|
| Lazy Loading (EF Proxies) | Automatically loads related data on demand | Low: each access is a new SQL query (N+1) |
| Eager Loading (Include/ThenInclude) | Explicitly specify which data to load | High: one SQL with JOIN, but fetches all fields |
| Explicit Loading | Manually load related data after the main query | Medium: flexible control, but more code |
| Projection (Select to DTO) | Project only needed fields without tracking | Optimal: minimal data, no tracking |
Stack and Approaches
Base stack: ASP.NET Core, EF Core + PostgreSQL (Npgsql) or MS SQL Server, MediatR for CQRS pattern, FluentValidation, Serilog for structured logs to Elasticsearch/Seq.
Authentication — ASP.NET Core Identity + JWT Bearer via Microsoft.AspNetCore.Authentication.JwtBearer. For enterprise apps — integration with Azure AD / Microsoft Entra ID via Microsoft.Identity.Web: a couple of config lines and MSAL on the mobile client provide SSO out of the box.
Push notifications: Azure Notification Hubs if infrastructure is in Azure — a managed service on top of FCM and APNs, scales to millions of devices. Alternative — direct integration via official FirebaseAdmin NuGet and dotnet-apns (HTTP/2).
Case Study: Optimizing an Analytical Report
Enterprise mobile app for 3000 employees, iOS + Android. Backend — ASP.NET Core, MS SQL Server, Azure Service Bus for event bus. Problem: endpoint /api/reports/summary executed in 4–8 seconds, exceeding the mobile client timeout. Root cause — EF Core built a query with 6 JOINs through navigation properties, MS SQL didn't use indexes due to a CAST in the WHERE clause. Solution: switched to Dapper for analytical queries, added a computed index. Result: 180ms — over 20x reduction. This optimization saved the client $12,000 per year in server costs.
Why Use CQRS with MediatR for .NET Backend Development
For mobile APIs, CQRS is justified even on small projects: read models optimized for client screens (no extra fields), write models for business logic. MediatR pipeline behavior is a convenient place for validation (FluentValidation), logging, retry policies (Polly).
// Query handler with projection — only needed fields public async Task<ProductListDto> Handle(GetProductsQuery request, ...) { return await _context.Products .Where(p => p.IsActive) .Select(p => new ProductListDto(p.Id, p.Name, p.Price, p.ThumbnailUrl)) .ToListAsync(cancellationToken); } SignalR for Realtime
If the mobile client needs realtime (chat, live tracking, realtime notifications) — SignalR with Azure SignalR Service for horizontal scaling. On iOS, the SignalR client (SignalRClient via microsoft-signalr npm or SwiftSignalRClient) supports WebSocket with automatic fallback to Long Polling.
Setting Up Realtime Functionality in a Mobile App
- Install NuGet package
Microsoft.AspNetCore.SignalRon the server and configure Hub inStartup.cs. - Connect the client: on iOS use
SwiftSignalRClient, on Android usesignalr-clientfor Kotlin. - For scaling, use Azure SignalR Service — it manages WebSocket connections and automatically falls back to Long Polling during network issues.
- Security: pass JWT token in query string when establishing connection and validate it in Hub via
Context.User.
Deployment
Docker + Azure Container Apps or AKS. dotnet publish --configuration Release -r linux-x64 with --self-contained gives a binary without .NET Runtime dependency in the image (but increases size). For Kubernetes — health checks via IHealthCheck interface, liveness and readiness endpoints.
What's Included
- API project: OpenAPI/Swagger specification, full endpoint documentation.
- Database migrations (Entity Framework Migrations or scripts).
- CI/CD configuration (Azure DevOps, GitHub Actions).
- Deployment instructions (Docker, Kubernetes).
- Code review and load testing.
- 2 months of post-delivery support (bug fixes, consultations).
Timelines: API with 15–20 methods, Identity, pushes, Azure integration — 4–6 weeks. Enterprise system with AD, Service Bus, complex role model — 10–16 weeks. Contact us for a backend development quote — we'll assess your project in one day and propose the optimal architecture.
Microsoft Docs: ASP.NET Core SignalR overview Wikipedia: CQRS







