Introduction
In this article, we will learn about 𝗪𝗲𝗯 𝗔𝗣𝗜 𝗔𝗻𝘁𝗶-𝗣𝗮𝘁𝘁𝗲𝗿𝗻𝘀 𝗧𝗵𝗮𝘁 𝗕𝗿𝗲𝗮𝗸 𝗬𝗼𝘂𝗿 .𝗡𝗘𝗧 𝗔𝗽𝗽𝘀 𝗶𝗻 𝗣𝗿𝗼𝗱𝘂𝗰𝘁𝗶𝗼𝗻.
Building a Web API that works on your machine is easy. Building one that survives production traffic, failures, security threats, and scale is a different challenge entirely
Here are common ASP.NET Core Web API anti-patterns that often cause outages, performance degradation, and maintenance nightmares.
Let's get started.
1. Returning 200 OK for Everything
Anti-Pattern
return Ok(new
{
Success = false,
Message = "User not found"
});Why It's Bad
Clients cannot distinguish between successful and failed requests using HTTP semantics.
Better Approach
return NotFound("User not found");Use proper status codes:
200 OK201 Created400 Bad Request401 Unauthorized403 Forbidden404 Not Found500 Internal Server Error
2. Catching Every Exception Globally and Hiding Details
Anti-Pattern
try
{
...
}
catch(Exception)
{
return StatusCode(500);
}Problems
Loses debugging information
Hides root causes
Makes production support difficult
Better Approach
Use centralized exception middleware:
app.UseExceptionHandler();Log exceptions with:
ILogger<T>Return standardized problem details.
return Problem(
title: "Unexpected error occurred",
statusCode: 500);3. Synchronous Database Calls
Anti-Pattern
var users = _context.Users.ToList();Why It's Dangerous
Under load:
Blocks threads
Reduces throughput
Causes thread pool starvation
Better Approach
var users = await _context.Users.ToListAsync();
``Use async end-to-end.
4. Fat Controllers
Anti-Pattern
[HttpPost]
public IActionResult CreateOrder(...)
{
// validation
// business logic
// database updates
// notifications
// email sending
}Problems
Hard to test
Hard to maintain
Violates separation of concerns
Better Approach
await _orderService.CreateOrderAsync(request);Keep controllers thin.
5. Exposing EF Core Entities Directly
Anti-Pattern
return Ok(customerEntity);Problems
Leaks internal structure
Serialization issues
Security risks
Circular references
Better Approach
Use DTOs:
public record CustomerDto(
int Id,
string Name,
string Email);
``Map entities to DTOs.
6. Overfetching Data
Anti-Pattern
var users = await _context.Users
.Include(x => x.Orders)
.Include(x => x.Payments)
.Include(x => x.Addresses)
.ToListAsync();Problems
Huge payloads
Slow SQL
Memory pressure
Better Approach
Project only required fields:
var users = await _context.Users
.Select(u => new UserListDto
{
Id = u.Id,
Name = u.Name
})
.ToListAsync();7. Missing API Versioning
Anti-Pattern
Deploying breaking changes directly.
/api/customersResult
Existing consumers suddenly fail.
Better Approach
/api/v1/customers
/api/v2/customersOr use header-based versioning.
8. No Request Validation
Anti-Pattern
public async Task<IActionResult> Create(UserRequest request)
{
// directly process
}Problems
Invalid data enters system
Database corruption
Unexpected exceptions
Better Approach
Use:
[ApiController]and FluentValidation:
RuleFor(x => x.Email)
.NotEmpty()
.EmailAddress();9. Ignoring Cancellation Tokens
Anti-Pattern
public async Task<IActionResult> Get()
{
await _service.ProcessAsync();
}Problem
Work continues even after:
Browser closes
Mobile app disconnects
Load balancer times out
Better Approach
public async Task<IActionResult> Get(
CancellationToken ct)
{
await _service.ProcessAsync(ct);
}10. Logging Too Little or Too Much
Too Little
_logger.LogError("Error");No context.
Too Much
_logger.LogInformation(JsonSerializer.Serialize(request));May expose:
Passwords
Tokens
PII
Better Approach
Structured logging:
_logger.LogInformation(
"Creating order {OrderId} for customer {CustomerId}",
orderId,
customerId);11. No Rate Limiting
Anti-Pattern
API accepts unlimited requests.
Risks
DDoS attacks
Resource exhaustion
Database overload
Better Approach (.NET 7+)
builder.Services.AddRateLimiter(...);
app.UseRateLimiter();Protect critical endpoints.
12. Ignoring Health Checks and Observability
Anti-Pattern
You only discover problems after customers complain.
Missing Components
Health checks
Metrics
Tracing
Dashboards
Better Approach
builder.Services.AddHealthChecks();
app.MapHealthChecks("/health");Add:
OpenTelemetry
Application Insights
Prometheus
Grafana
for proactive monitoring.
Production-Ready API Checklist
✅ Proper HTTP status codes
✅ Global exception handling
✅ Async all the way
✅ Thin controllers
✅ DTOs instead of entities
✅ Request validation
✅ API versioning
✅ Cancellation tokens
✅ Structured logging
✅ Rate limiting
✅ Health checks
✅ Observability & tracing
The majority of production API issues in .NET applications are not caused by complex algorithms. They're caused by these architectural and operational anti-patterns that quietly accumulate until traffic, scale, or failures expose them. Fixing them early dramatically improves reliability, performance, and maintainability.
Conclusion
In this article, I have tried to cover Difference Between Controller and ControllerBase in ASP.NET Core.

Join the conversation! Your thoughts help the community grow.