Implementing Memory Guard in ASP.NET Core API: Tips for Setting Optimal Thresholds

Implementing Memory Guard in ASP.NET Core API: Tips for Setting Optimal Thresholds

Sep 5, 2025·

3 min read

Why Memory Guard Matters in Real‑World APIs

If you’ve been running ASP.NET Core APIs in production for any length of time, you’ll know that memory issues rarely announce themselves politely. They creep in — a little extra caching here, a big JSON payload there — until one day you’re staring at an IIS recycle or an OutOfMemoryException in the logs.

The .NET garbage collector is excellent, but it’s not a silver bullet. It can’t save you from unbounded caches, large object heap churn, or a DbContext that’s tracking far more entities than you intended. That’s why I like to add a Memory Guard middleware — a lightweight, configurable check that gives me an early warning before things get ugly.

The Middleware I Use

Here’s the exact implementation I’ve been running in ASP.NET Core 8 projects. It’s simple, production‑safe, and easy to tune per environment.

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace WebApi.Middleware;

public class MemoryGuardMiddleware(
    RequestDelegate next,
    ILogger<MemoryGuardMiddleware> logger,
    IConfiguration config)
{
    private readonly int _memoryThresholdMb = config.GetValue("MemoryGuard:ThresholdMB", 512);
    private readonly TimeSpan _sampleInterval = TimeSpan.FromSeconds(
        config.GetValue("MemoryGuard:SampleIntervalSeconds", 30));
    private DateTime _lastSampleTime = DateTime.MinValue;

    public async Task InvokeAsync(HttpContext context)
    {
        var now = DateTime.UtcNow;
        if (now - _lastSampleTime >= _sampleInterval)
        {
            _lastSampleTime = now;
            var processMemoryMb = Process.GetCurrentProcess().PrivateMemorySize64 / (1024 * 1024);

            if (processMemoryMb > _memoryThresholdMb)
            {
                logger.LogWarning(
                    "⚠ High memory usage detected: {ProcessMemoryMB} MB (threshold: {ThresholdMB} MB)",
                    processMemoryMb, _memoryThresholdMb);
            }
        }

        await next(context);
    }
}

appsettings.json:

{
  "MemoryGuard": {
    "ThresholdMB": 1500,
    "SampleIntervalSeconds": 30
  }
}

Program.cs:

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
var app = builder.Build();

app.UseMiddleware<MemoryGuardMiddleware>(); //Add here

app.MapControllers();
app.Run();

How I Pick the Right Thresholds

This is where experience (and a bit of measurement) comes in. The “right” numbers depend on your hosting setup, traffic patterns, and how much headroom you want before IIS or the OS steps in.

ThresholdMB

  • First, I measure the API’s steady‑state memory usage under normal load.

  • Then I set the threshold to about 70–80% of the IIS Private Memory limit (or the container/VM limit if self‑hosted).

  • Example:

    • IIS App Pool limit = 2 GB → ThresholdMB ≈ 1400–1600 MB

    • No explicit limit, 8 GB server, other services use ~4 GB → ThresholdMB ≈ 2500–3000 MB

SampleIntervalSeconds

  • Too frequent checks waste CPU and spam logs.

  • Too infrequent and you might miss a sudden leak.

  • I’ve found 30–60 seconds to be the sweet spot for most APIs.

My Go‑To Starting Point for ASP.NET Core 8 + IIS + EF Core

If I’m spinning up a new API and don’t have baseline data yet, I’ll start with:

  • ThresholdMB: 1500 MB

  • SampleIntervalSeconds: 30 seconds

Then I’ll watch logs for a week:

  • If I see warnings during normal load → I raise the threshold.

  • If I never see warnings but still get OOMs or recycles → I lower it.

Why This Works

This approach gives me:

  • Early warnings before memory issues become outages.

  • Low overhead — it’s just a quick check every 30 seconds.

  • Flexibility — I can tune it per environment without touching code.

And most importantly, it’s saved me from more than one “why is the API down?” call at 2 AM.

💡
Pro tip: Pair this with Application Insights alerts and IIS Private Memory limits for a complete safety net. That way, you’re not just reacting to problems — you’re catching them before your users notice.

Summary

Effectively managing memory usage in ASP.NET Core APIs is essential to avoid disruptions such as IIS recycles or OutOfMemoryExceptions. By implementing a configurable Memory Guard middleware, you can receive early alerts about high memory consumption, which helps in maintaining stable performance. Adjusting memory thresholds and sampling intervals according to specific environmental factors allows you to optimize resource management and prevent potential issues before they affect users.