Course contentsShow
← C#
Lesson 1846 of 1,90817. Deployment and Cloud ArchitectureFree lesson

Resource Limits and Request Tuning for Garbage Collection

Configure Kubernetes resource limits to prevent .NET Garbage Collector contention and OOM kills.

In this lesson, you will learn how to balance Kubernetes resource constraints with .NET’s memory management heuristics to prevent container crashes and performance degradation.

The Memory Mismatch Problem

By default, the .NET Garbage Collector (GC) queries the host OS for total physical memory to decide when to trigger collections. In a Kubernetes container, this can lead to disaster: if you set a hard memory limit (e.g., 512MB) but your container resides on a 64GB host node, the GC sees 64GB of available memory. It will delay collections until the pod hits the Kubernetes limit, resulting in an OOM (Out of Memory) kill before the GC even realizes it is under pressure.

Aligning GC with Container Limits

To fix this, .NET provides environment variables to force the GC to respect container quotas. Setting DOTNET_GCHeapHardLimit allows you to explicitly tell the GC how much memory it should manage.

When defining your Kubernetes deployment, you should ensure your resources.limits.memory matches this heap limit, accounting for the overhead of the runtime itself:

spec:
  containers:
  - name: my-dotnet-app
    resources:
      limits:
        memory: "512Mi"
    env:
    - name: DOTNET_GCHeapHardLimit
      value: "400Mi" # Keep a margin for non-heap memory

Preventing Contention with CPU Limits

Kubernetes CPU limits act as a throttle. If you set resources.limits.cpu too low, the GC threads—which run in parallel during background collections—may be starved of execution time. This forces your application to pause for "Stop-the-World" collections, significantly increasing latency.

If you have a multi-core environment, consider using the DOTNET_GCHeapCount setting. By pinning the number of GC heaps to match your CPU request, you prevent the GC from spawning more threads than the container can actually schedule, which reduces context switching overhead and improves throughput.

Why Request Tuning Matters

If your requests are too low, Kubernetes might place too many pods on a single node, causing resource contention. If your limits are too tight, the GC will run far too frequently, causing "GC thrashing," where the application spends more time reclaiming memory than executing business logic.

Key Takeaway: Always pair your Kubernetes memory limits with DOTNET_GCHeapHardLimit to ensure the .NET runtime recognizes its container boundaries and triggers collections before the OOM killer intervenes.