Memory problems in production are difficult to investigate because the application may continue running while memory usage keeps increasing.

A common reaction is to restart the application. Restarting can recover memory temporarily, but it also removes valuable diagnostic information. Objects that were consuming memory, blocked threads, large allocations, and the managed heap state can disappear as soon as the process stops.

A memory dump gives developers a snapshot of the running process that can be analyzed later.

In .NET applications, you can create a memory dump from a running process without restarting the application. This is especially useful when investigating memory leaks, excessive memory usage, unexpected garbage collection behavior, or high process memory.

This article explains how to collect a memory dump from a running C# application, what information the dump contains, how to collect it safely in production, and how to analyze it afterward.

What Is a Memory Dump?

A memory dump is a snapshot of a process at a particular point in time.

For a .NET application, the dump can contain information about:

  • Managed objects

  • Managed heap state

  • Threads

  • Stack information

  • Loaded assemblies

  • Native memory

  • Runtime information

  • Exception state

  • Application state

The exact information available depends on the dump type and platform.

Conceptually, the process looks like this:

Running .NET Application
          |
          v
     Process Memory
          |
          v
     Memory Dump
          |
          v
 Analyze Later

The important part is that creating the dump does not require stopping and restarting the application.

Why Create a Dump Without Restarting?

Restarting an application can hide the original problem.

Consider an application whose memory usage looks like this:

08:00  - 2 GB
09:00  - 3 GB
10:00  - 5 GB
11:00  - 8 GB

At 11:00, the application may be approaching its memory limit.

If you restart it:

8 GB
 |
 v
Restart
 |
 v
2 GB

The immediate memory problem appears to disappear.

But the objects that caused the memory growth are no longer available for investigation.

A dump collected before the restart can preserve useful diagnostic information.

When Should You Collect a Memory Dump?

A memory dump can be useful when you see symptoms such as:

  • Increasing process memory

  • Frequent garbage collections

  • Out-of-memory exceptions

  • Unexpected application slowdown

  • Large managed heap

  • Threading problems

  • Suspected memory leaks

  • Increasing container memory usage

  • Memory usage that does not fall after garbage collection

Do not automatically create a dump every time memory increases.

First confirm that the process is experiencing a meaningful problem.

What You Need Before Collecting a Dump

Before collecting a production dump, identify:

  1. The process ID.

  2. The operating system.

  3. The .NET runtime version.

  4. Available disk space.

  5. The location where the dump will be stored.

  6. Whether your production policy permits process dumps.

  7. Whether the dump could contain sensitive information.

A dump can contain application data that was present in memory.

For example:

Passwords
Tokens
Connection information
Customer data
Request data
Personal information

Do not treat a production memory dump like an ordinary log file.

Using dotnet-dump

The .NET diagnostics tools include dotnet-dump, which can be used to collect and analyze dumps from .NET processes.

A typical workflow is:

Find process
    |
    v
Collect dump
    |
    v
Copy dump if required
    |
    v
Analyze dump
    |
    v
Identify memory problem

The tool can collect a dump from a running .NET process.

Step 1 - Find the Running Process

Start by listing the running .NET processes.

dotnet-dump ps

The output can identify processes such as:

      12345  MyApplication
      15678  WorkerService
      17321  ApiService

The number is the process ID.

For example:

PID = 12345

You can also identify the process through the operating system's normal process-management tools.

The important point is to make sure you select the correct application before collecting a dump.

Step 2 - Check Available Disk Space

A dump file can be large.

Before collecting it, check the available disk space:

df -h

on Linux systems.

On Windows, check the available space on the drive where the dump will be written.

Do not assume that a dump will always be small.

The required storage depends on the process and the type of dump being collected.

Step 3 - Collect the Dump

A basic dotnet-dump command looks like this:

dotnet-dump collect --process-id 12345 --output /tmp/myapp.dmp

The important parameters are:

--process-id

This identifies the running process.

--output

This specifies where the dump should be written.

For example:

dotnet-dump collect \
  --process-id 12345 \
  --output /tmp/myapp-memory.dmp

The application continues running while the dump is collected.

The exact collection behavior and available dump options can depend on the operating system and runtime.

What Happens During Collection?

At a high level:

.NET Process
     |
     | 1. Diagnostic request
     v
Dump collection
     |
     | 2. Capture process state
     v
.dmp file
     |
     | 3. Application continues
     v
Running application

The application is not intentionally restarted as part of the dump collection process.

However, collecting a dump is not free.

The process can experience additional CPU, memory, and I/O activity while the snapshot is being created.

For this reason, dump collection should still be treated as a production diagnostic operation.

Full Dump vs Smaller Diagnostic Data

A full process dump can contain a large amount of memory.

That can be useful when investigating:

  • Object retention

  • Managed heap problems

  • Native memory

  • Memory corruption

  • Complex runtime issues

But a larger dump also means:

  • More disk usage

  • Longer collection time

  • More data to transfer

  • Greater security exposure

  • More storage requirements

Choose the collection approach based on the problem you are investigating.

Do not collect the largest possible dump simply because it contains more information.

Example Production Workflow

Suppose an ASP.NET Core API is running on Linux.

The application has:

PID: 12345
Memory: 7.8 GB

The normal memory usage is approximately:

2 - 3 GB

The first step is to confirm the process:

dotnet-dump ps

Then collect the dump:

dotnet-dump collect \
  --process-id 12345 \
  --output /var/tmp/api-memory.dmp

After collection, verify the file:

ls -lh /var/tmp/api-memory.dmp

The application can continue serving requests while the dump is moved for analysis.

Moving a Production Dump

A production dump should be handled carefully.

A typical workflow is:

Production Server
       |
       v
Collect dump
       |
       v
Secure storage
       |
       v
Diagnostic environment
       |
       v
Analysis

Avoid leaving diagnostic dumps on production servers indefinitely.

Once the investigation is complete, follow your organization's retention and deletion requirements.

Analyzing the Dump

After collecting the dump, open it using dotnet-dump.

For example:

dotnet-dump analyze /tmp/myapp-memory.dmp

You can then use diagnostic commands from the interactive session.

A useful first command is:

dumpheap -stat

This can provide information about managed objects and their memory usage.

A simplified result might look like:

Count        Total Size     Type
------------------------------------------------
125000       48 MB          System.String
85000        35 MB          MyApp.Customer
42000        28 MB          MyApp.Order
12000        22 MB          System.Byte[]

This kind of information can help identify object types that are consuming significant amounts of managed memory.

Finding Large Objects

Large objects can contribute significantly to memory pressure.

For example, a service that repeatedly creates large byte arrays may produce:

public byte[] CreateBuffer()
{
    return new byte[10_000_000];
}

If references to those arrays remain alive longer than expected, memory usage can increase.

A heap analysis can help determine whether large object types are accumulating.

The important question is not simply:

Which object is large?

It is:

Why is this object still reachable?

Finding Object Retention

Suppose the dump shows many instances of:

MyApp.Session

The next question is why those objects have not been collected.

Possible causes include:

Static collection
      |
      v
Session objects

or:

Long-lived service
      |
      v
Cache
      |
      v
Session objects

The dump can help developers follow object references and determine why memory remains reachable.

This is often more useful than simply looking at total process memory.

Memory Usage Does Not Always Mean a Memory Leak

High memory usage does not automatically mean that the application has a memory leak.

The application may legitimately allocate memory for:

  • Caching

  • Large requests

  • Serialization

  • Background processing

  • Temporary buffers

  • Database operations

For example:

var results = await repository.GetLargeResultSetAsync();

var response = JsonSerializer.Serialize(results);

This can create several in-memory representations of the same logical data.

A better investigation should therefore look at memory behavior over time rather than assuming that high memory equals a leak.

Compare Multiple Dumps

One dump provides a snapshot.

Two or more dumps can provide a trend.

For example:

Dump 1
2.5 GB

        |
        | 30 minutes
        v

Dump 2
4.0 GB

        |
        | 30 minutes
        v

Dump 3
6.5 GB

If the same object types continue increasing between dumps, that can provide stronger evidence of object retention.

A practical investigation can therefore use:

Dump A
   +
Dump B
   +
Application metrics
   +
Garbage collection data

This gives a broader picture than a single snapshot.

Common Production Mistakes

Restarting Before Collecting the Dump

If the goal is to understand the current memory problem, restarting first can destroy useful evidence.

Saving the Dump on a Nearly Full Disk

A large dump can consume substantial storage.

Always check available space first.

Collecting Dumps Without Authorization

Production dumps may contain sensitive application data.

Follow your organization's security and privacy procedures.

Assuming a Large Dump Means a Leak

Memory usage needs to be analyzed in context.

Looking Only at Object Counts

An object can have a high count but relatively small total memory usage.

Look at both count and total size.

Ignoring Native Memory

A managed heap investigation may not explain all process memory usage.

The application can also consume native memory.

Troubleshooting

dotnet-dump Cannot Find the Process

First confirm that the process is a .NET process and that the process ID is correct.

Run:

dotnet-dump ps

Then verify the target process again.

Dump Collection Fails

Check:

[ ] Process ID
[ ] Tool installation
[ ] Runtime compatibility
[ ] User permissions
[ ] Available disk space
[ ] Output directory permissions

The Dump Is Too Large

Review whether the selected dump type is appropriate for the problem.

Also check the amount of memory currently used by the process.

Analysis Is Very Slow

Large dumps can require significant CPU, memory, and disk resources during analysis.

Analyze the dump on a machine with enough resources rather than putting additional pressure on the production server.

The Dump Does Not Explain the Problem

A single dump may not be enough.

Collect another dump later and compare the object population and application metrics.

Best Practices

Collect Before Restarting

When possible, capture the evidence before restarting a problematic process.

Use a Dedicated Diagnostic Location

Do not mix dumps with application logs and normal temporary files.

Secure the Dump

Treat production dumps as sensitive data.

Record the Context

For every dump, record:

Application
Process ID
Server
Date and time
Memory usage
CPU usage
Application version
Runtime version
Reason for collection

This information makes later analysis much easier.

Keep Application Metrics

A dump is much more useful when combined with metrics showing:

Process memory
GC heap size
CPU usage
Request rate
Error rate
GC activity

Analyze Outside Production

Where possible, transfer the dump to a controlled diagnostic environment.

This reduces additional resource pressure on the production application.

Advantages

  1. No application restart is required to capture the current process state.

  2. Production memory problems can be investigated using real application state.

  3. Managed objects can be examined to identify suspicious memory usage.

  4. Multiple dumps can be compared to investigate object growth.

  5. The application can continue running after the collection operation completes.

Disadvantages and Trade-Offs

  1. Dump files can be very large.

  2. Collection can temporarily consume additional resources.

  3. Production dumps can contain sensitive information.

  4. Analysis can require significant CPU and memory.

  5. A single dump may not be enough to identify the root cause.

  6. Native memory issues may require additional diagnostic techniques.

Production Memory Investigation Checklist

Use the following checklist when investigating a memory problem:

[ ] Confirm abnormal memory behavior
[ ] Identify the affected process
[ ] Record application and runtime versions
[ ] Check available disk space
[ ] Verify permission to collect diagnostics
[ ] Collect the dump before restarting
[ ] Store the dump securely
[ ] Record application metrics
[ ] Analyze managed heap usage
[ ] Investigate object retention
[ ] Check for native memory usage
[ ] Compare additional dumps when necessary
[ ] Identify the root cause
[ ] Remove the dump according to retention policy
[ ] Apply and validate the fix

Conclusion

A memory dump is one of the most useful diagnostic tools for investigating a problematic .NET application without immediately restarting it.

Using dotnet-dump, developers can capture the state of a running process and analyze managed objects, heap usage, threads, and other runtime information afterward.

The most important part is not simply creating the dump. The real value comes from collecting it at the right time, securing it properly, analyzing object retention, and combining the results with application metrics.

When a production application is consuming unusual amounts of memory, restarting may restore service temporarily, but collecting a dump first can preserve the evidence needed to understand what happened.

For production troubleshooting, the practical workflow is straightforward:

Observe
   |
   v
Confirm abnormal memory usage
   |
   v
Collect dump without restarting
   |
   v
Secure and analyze
   |
   v
Identify retention or allocation problem
   |
   v
Fix and validate

This approach turns a temporary production symptom into useful diagnostic evidence that can help developers find and fix the underlying memory problem.