APM Tips

Application Insights

Disable Application Insights in development and debug builds

Updated · 5 min read · By APM Tips editorial team

Decide per environment at startup. With the classic Application Insights SDK 2.x, set DisableTelemetry to true when the app runs in Development; with the OpenTelemetry distros, do not register the Azure Monitor exporter in Development, or send the Microsoft OpenTelemetry Distro's output to the console instead. Developer mode is not an off switch: it sends telemetry faster, not less.

Every Application Insights setup eventually hits the same question: the app works, the telemetry works, and now every dotnet run on a laptop adds requests, exceptions and dependency calls to the production resource. The fix is an environment check at startup. What you check, and what you turn off, depends on which of four packages the app uses.

The short answer, by stack

StackOff in developmentPackage
Classic SDK 2.x, ASP.NET CoreDisableTelemetry = true on TelemetryConfigurationMicrosoft.ApplicationInsights.AspNetCore 2.x
Classic SDK 2.x, other .NET hostsTelemetryConfiguration.Active.DisableTelemetry = trueMicrosoft.ApplicationInsights 2.x
Application Insights SDK 3.xKeep a connection string; disable or redirect by environmentMicrosoft.ApplicationInsights.* 3.x
Azure Monitor OpenTelemetry DistroDon’t call UseAzureMonitor() in DevelopmentAzure.Monitor.OpenTelemetry.AspNetCore
Microsoft OpenTelemetry DistroExporters = ExportTarget.Console in DevelopmentMicrosoft.OpenTelemetry, @microsoft/opentelemetry
Node.js classic SDK 2.xconfig.disableAppInsights = trueapplicationinsights 2.x

Classic Application Insights SDK 2.x (.NET)

ASP.NET Core

The 2.x ASP.NET Core package registers a TelemetryConfiguration in dependency injection. Set its DisableTelemetry flag when the host environment is Development:

using Microsoft.ApplicationInsights.Extensibility;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddApplicationInsightsTelemetry();

if (builder.Environment.IsDevelopment())
{
    builder.Services.Configure<TelemetryConfiguration>(config => config.DisableTelemetry = true);
}

var app = builder.Build();

Keep the AddApplicationInsightsTelemetry() call itself. Classes that take a TelemetryClient in their constructor still resolve, and TrackEvent calls still run; nothing leaves the process.

Microsoft’s documentation is precise about what this flag does: it stops telemetry being sent. It does not stop the automatic collection modules from collecting. That is fine for a laptop, but if the goal is to save CPU in a test environment, remove the collection modules you don’t need as well.

ASP.NET on .NET Framework and other hosts

Older apps configure the SDK through ApplicationInsights.config and the static TelemetryConfiguration.Active. Flip the same flag early, in Application_Start or the console app’s Main:

#if DEBUG
TelemetryConfiguration.Active.DisableTelemetry = true;
#endif

A compile-time #if DEBUG is the bluntest version of the check: a Release build run locally will still send. Prefer an app setting or environment variable you control when you can.

Developer mode is not an off switch

The 2.x SDK also has a developer mode, and its name sends people the wrong way:

TelemetryConfiguration.Active.TelemetryChannel.DeveloperMode = true;

Developer mode makes the channel send each item straight away instead of batching, and the SDK includes a module that switches it on automatically while a debugger is attached. You see your telemetry sooner, with extra diagnostic messages. You also send more requests, and Microsoft advises turning it off in production because it can slow the app down. If you were looking for “off”, you want DisableTelemetry.

Application Insights .NET SDK 3.x

SDK 3.x keeps most of the TelemetryClient and TelemetryConfiguration API but runs on OpenTelemetry underneath, and three changes matter here:

  • A connection string is required. 3.x can fail at startup without one, so “leave it empty locally” no longer works. For tests and local runs Microsoft suggests a dummy value such as InstrumentationKey=00000000-0000-0000-0000-000000000000.
  • TelemetryConfiguration.Active is gone. Create configuration with TelemetryConfiguration.CreateDefault().
  • The channel abstraction is removed, and developer mode went with it. Batching is the exporter’s job now.

A practical development setup for 3.x is a dummy connection string in appsettings.Development.json, so the app starts, and a DisableTelemetry setting for the same environment if your configuration supports it (it appears in the 3.x applicationinsights.config schema). If you’d rather see the data, point Development at a separate resource instead.

Azure Monitor OpenTelemetry Distro (.NET)

Apps on Azure.Monitor.OpenTelemetry.AspNetCore turn everything on with one call, which reads APPLICATIONINSIGHTS_CONNECTION_STRING from the environment. The simplest development switch is not to make that call:

var builder = WebApplication.CreateBuilder(args);

if (!builder.Environment.IsDevelopment())
{
    builder.Services.AddOpenTelemetry().UseAzureMonitor();
}

var app = builder.Build();

Call it exactly once. The distro creates a single tracer, meter and logger provider, and a second UseAzureMonitor() throws NotSupportedException. If you still want to see spans locally, add an exporter of your own in Development, such as the OpenTelemetry console exporter or an OTLP exporter pointed at a local dashboard.

Microsoft now recommends a newer package for new apps (next section) but says existing users of this distro need take no action.

Microsoft OpenTelemetry Distro

The Microsoft OpenTelemetry Distro (Microsoft.OpenTelemetry for .NET, @microsoft/opentelemetry for Node.js) is what Microsoft points new .NET, Node.js and Python apps to. Don’t initialise it alongside the Azure Monitor distro in the same app.

.NET

Its Exporters option chooses where telemetry goes, and the console is one of the targets. That makes the development switch a one-liner that keeps all the instrumentation running:

using Microsoft.OpenTelemetry;

var builder = WebApplication.CreateBuilder(args);

builder.UseMicrosoftOpenTelemetry(options =>
{
    options.Exporters = builder.Environment.IsDevelopment()
        ? ExportTarget.Console
        : ExportTarget.AzureMonitor;
});

var app = builder.Build();
app.Run();

If you leave Exporters unset, the distro detects destinations itself: Azure Monitor export is enabled only when a connection string is configured. Not setting APPLICATIONINSIGHTS_CONNECTION_STRING on developer machines therefore works too, but the explicit version above is easier to read six months later.

Node.js

The Node.js distro enables Azure Monitor export when you pass it an azureMonitor block. Pass it only when a connection string exists:

const { useMicrosoftOpenTelemetry } = require("@microsoft/opentelemetry");

const connectionString = process.env.APPLICATIONINSIGHTS_CONNECTION_STRING;

if (connectionString) {
  useMicrosoftOpenTelemetry({
    azureMonitor: {
      azureMonitorExporterOptions: { connectionString },
    },
  });
}

Run this before the libraries you want instrumented are loaded; ESM apps preload a bootstrap file with node --import. The distro needs Node.js 22 or later.

Node.js classic SDK 2.x

The retired applicationinsights 2.x package has a client-level switch:

const appInsights = require("applicationinsights");

appInsights.setup(process.env.APPLICATIONINSIGHTS_CONNECTION_STRING).start();

if (process.env.NODE_ENV !== "production") {
  appInsights.defaultClient.config.disableAppInsights = true;
}

Its own “developer mode” recipe (internal logging on, maxBatchSize of 0) again means send immediately, not don’t send.

Check that nothing is sent

Whichever switch you use, prove it once:

  1. Start the app locally and exercise a few endpoints.
  2. Open Live Metrics for the production resource. With the switch working, your machine never appears as a server.
  3. In Logs, look for your host name in cloud_RoleInstance over the last 30 minutes. No rows is the answer you want.

Then put the check in code review: the environment condition sits next to the registration, where the next person to change startup will see it.

Frequently asked questions

Does developer mode turn Application Insights off?

No. In the classic 2.x SDK, developer mode makes the telemetry channel send items immediately instead of batching them, so you see data sooner while debugging. Microsoft advises switching it off in production because it can slow the app down. It was removed in SDK 3.x together with the channel abstraction.

Can I just leave the connection string empty on my machine?

It depends on the package. The Microsoft OpenTelemetry Distro for .NET only turns on Azure Monitor export when a connection string is set and Exporters is not set explicitly, so an empty value is a valid off switch there. Application Insights .NET SDK 3.x requires a connection string and can fail at startup without one. For the Azure Monitor OpenTelemetry Distro, skip the UseAzureMonitor() call instead of relying on a missing value.

Should development send telemetry to its own Application Insights resource?

If you want telemetry while you debug, yes. Point Development at a separate resource through its own APPLICATIONINSIGHTS_CONNECTION_STRING so local traffic, test exceptions and half-finished features never mix with production data, alerts or cost.

Sources, checked

  1. Monitor .NET and Node.js applications with Application Insights (Classic API 2.x)learn.microsoft.com · checked
  2. Migrate Application Insights Classic API SDKs to OpenTelemetrylearn.microsoft.com · checked
  3. Enable OpenTelemetry in Application Insightslearn.microsoft.com · checked
  4. Azure Monitor Distro client library for .NETlearn.microsoft.com · checked
  5. Microsoft.OpenTelemetry (Microsoft OpenTelemetry Distro for .NET), READMEgithub.com · checked