---
title: Instrumenting .NET Serverless Applications
description: Datadog, the leading service for cloud-scale monitoring.
breadcrumbs: >-
  Docs > Serverless > Serverless Monitoring for AWS Lambda > Instrument AWS
  Lambda applications > Instrumenting .NET Serverless Applications
---

# Instrumenting .NET Serverless Applications

{% alert level="info" %}
Version 67+ of the Datadog Lambda Extension is optimized to significantly reduce cold start duration. [Read more](https://docs.datadoghq.com/serverless/aws_lambda/configuration/?tab=datadogcli#using-datadog-lambda-extension-v67).
{% /alert %}

{% callout %}
##### Agentically add Datadog to your Lambda Functions

Agentic onboarding for Datadog Serverless is in Preview. Use your favorite AI coding tool such as Cursor or Claude to bulk-add Datadog monitoring to your Lambda functions.

[Request Access](https://www.datadoghq.com/product-preview/agentic-onboarding-for-serverless-applications/)
{% /callout %}

## Setup{% #setup %}

{% tab title="Datadog UI" %}
You can instrument your .NET AWS Lambda application directly within Datadog. Navigate to the [Serverless > AWS Lambda](https://app.datadoghq.com/functions?cloud=aws) page and select [**Instrument Functions**](https://app.datadoghq.com/serverless/aws/lambda/setup).

For more information, see [Remote instrumentation for AWS Lambda](https://docs.datadoghq.com/serverless/aws_lambda/remote_instrumentation).
{% /tab %}

{% tab title="Datadog CLI" %}
The Datadog CLI modifies existing Lambda functions' configurations to enable instrumentation without requiring a new deployment. It is the quickest way to get started with Datadog's serverless monitoring.

1. Install the Datadog CLI client

   ```sh
   npm install -g @datadog/datadog-ci @datadog/datadog-ci-plugin-lambda
   ```

1. If you are new to Datadog serverless monitoring, launch the Datadog CLI in interactive mode to guide your first installation for a quick start, and you can ignore the remaining steps. To permanently install Datadog for your production applications, skip this step and follow the remaining ones to run the Datadog CLI command in your CI/CD pipelines *after* your normal deployment.

   ```sh
   datadog-ci lambda instrument -i
   ```

1. Configure the AWS credentials

The Datadog CLI requires access to the AWS Lambda service and depends on the AWS JavaScript SDK to [resolve the credentials](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html). Ensure your AWS credentials are configured using the same method you would use when invoking the AWS CLI.

1. Configure the Datadog site

   ```sh
   export DATADOG_SITE="<DATADOG_SITE>"
   ```

Replace `<DATADOG_SITE>` with  (ensure the correct SITE is selected on the right).

1. Configure the Datadog API key

Datadog recommends saving the Datadog API key in AWS Secrets Manager for security and easy rotation. The key needs to be stored as a plaintext string (not a JSON blob). Ensure your Lambda functions have the required `secretsmanager:GetSecretValue` IAM permission.

   ```sh
   export DATADOG_API_KEY_SECRET_ARN="<DATADOG_API_KEY_SECRET_ARN>"
   ```

For quick testing purposes, you can also set the Datadog API key in plaintext:

   ```sh
   export DATADOG_API_KEY="<DATADOG_API_KEY>"
   ```

1. Instrument your Lambda functions

**Note**: Instrument your Lambda functions in a dev or staging environment first! Should the instrumentation result be unsatisfactory, run `uninstrument` with the same arguments to revert the changes.

To instrument your Lambda functions, run the following command.

   ```sh
   datadog-ci lambda instrument -f <functionname> -f <another_functionname> -r <aws_region> -v 23 -e 94
   ```

To fill in the placeholders:

   - Replace `<functionname>` and `<another_functionname>` with your Lambda function names. Alternatively, you can use `--functions-regex` to automatically instrument multiple functions whose names match the given regular expression.
   - Replace `<aws_region>` with the AWS region name.

Additional parameters can be found in the [CLI documentation](https://docs.datadoghq.com/serverless/serverless_integrations/cli).

{% /tab %}

{% tab title="Serverless Framework" %}
The [Datadog Serverless Plugin](https://docs.datadoghq.com/serverless/serverless_integrations/plugin) automatically configures your functions to send metrics, traces, and logs to Datadog through the [Datadog Lambda Extension](https://docs.datadoghq.com/serverless/libraries_integrations/extension).

To install and configure the Datadog Serverless Plugin, follow these steps:

1. Install the Datadog Serverless Plugin:

   ```sh
   serverless plugin install --name serverless-plugin-datadog
   ```

1. Update your `serverless.yml`:

   ```yaml
   custom:
     datadog:
       site: <DATADOG_SITE>
       apiKeySecretArn: <DATADOG_API_KEY_SECRET_ARN>
   ```

To fill in the placeholders:

   - Replace `<DATADOG_SITE>` with  (ensure the correct SITE is selected on the right).
   - Replace `<DATADOG_API_KEY_SECRET_ARN>` with the ARN of the AWS secret where your [Datadog API key](https://app.datadoghq.com/organization-settings/api-keys) is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The `secretsmanager:GetSecretValue` permission is required. For quick testing, you can instead use `apiKey` and set the Datadog API key in plaintext.

For more information and additional settings, see the [plugin documentation](https://docs.datadoghq.com/serverless/serverless_integrations/plugin).

{% /tab %}

{% tab title="AWS SAM" %}
The [Datadog CloudFormation macro](https://docs.datadoghq.com/serverless/serverless_integrations/macro) automatically transforms your SAM application template to install Datadog on your functions using Lambda layers, and configures your functions to send metrics, traces, and logs to Datadog through the [Datadog Lambda Extension](https://docs.datadoghq.com/serverless/libraries_integrations/extension).

1. Install the Datadog CloudFormation macro

Run the following command with your [AWS credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) to deploy a CloudFormation stack that installs the macro AWS resource. You only need to install the macro **once** for a given region in your account. Replace `create-stack` with `update-stack` to update the macro to the latest version.

   ```sh
   aws cloudformation create-stack \
     --stack-name datadog-serverless-macro \
     --template-url https://datadog-cloudformation-template.s3.amazonaws.com/aws/serverless-macro/latest.yml \
     --capabilities CAPABILITY_AUTO_EXPAND CAPABILITY_IAM
   ```

The macro is now deployed and ready to use.

1. Instrument your Lambda functions

Add the `DatadogServerless` transform **after** the `AWS::Serverless` transform under the `Transform` section in your `template.yml` file for SAM.

   ```yaml
   Transform:
     - AWS::Serverless-2016-10-31
     - Name: DatadogServerless
       Parameters:
         stackName: !Ref "AWS::StackName"
         dotnetLayerVersion: 23
         extensionLayerVersion: 94
         site: "<DATADOG_SITE>"
         apiKeySecretArn: "<DATADOG_API_KEY_SECRET_ARN>"
   ```

To fill in the placeholders:

   - Replace `<DATADOG_SITE>` with  (ensure the correct SITE is selected on the right).
   - Replace `<DATADOG_API_KEY_SECRET_ARN>` with the ARN of the AWS secret where your [Datadog API key](https://app.datadoghq.com/organization-settings/api-keys) is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The `secretsmanager:GetSecretValue` permission is required. For quick testing, you can use `apiKey` instead and set the Datadog API key in plaintext.

More information and additional parameters can be found in the [macro documentation](https://docs.datadoghq.com/serverless/serverless_integrations/macro).

{% /tab %}

{% tab title="AWS CDK" %}

{% alert level="info" %}
Instrumenting Dotnet functions through the Datadog CDK construct is only available for AWS CDK apps written in Typescript, Python, and Go.
{% /alert %}

The [Datadog CDK construct](https://github.com/DataDog/datadog-cdk-constructs) automatically installs Datadog on your functions using Lambda layers. It configures your functions to send metrics, traces, and logs to Datadog through the Datadog Lambda Extension.

### TypeScript{% #typescript %}

1. Install the Datadog CDK constructs library

For AWS CDK v1:

   ```sh
   npm install datadog-cdk-constructs --save-dev
   ```

For AWS CDK v2:

   ```sh
   npm install datadog-cdk-constructs-v2 --save-dev
   ```

1. Instrument your Lambda functions

For AWS CDK v1:

   ```typescript
   import { Datadog } from "datadog-cdk-constructs";
   
   const datadog = new Datadog(this, "Datadog", {
       dotnetLayerVersion: 23,
       extensionLayerVersion: 94,
       site: "<DATADOG_SITE>",
       apiKeySecretArn: "<DATADOG_API_KEY_SECRET_ARN>"
   });
   datadog.addLambdaFunctions([<LAMBDA_FUNCTIONS>])
   ```

For AWS CDK v2:

   ```typescript
   import { DatadogLambda } from "datadog-cdk-constructs-v2";
   
   const datadogLambda = new DatadogLambda(this, "datadogLambda", {
       dotnetLayerVersion: 23,
       extensionLayerVersion: 94,
       site: "<DATADOG_SITE>",
       apiKeySecretArn: "<DATADOG_API_KEY_SECRET_ARN>"
   });
   datadogLambda.addLambdaFunctions([<LAMBDA_FUNCTIONS>])
   ```

### Python{% #python %}

1. Install the Datadog CDK constructs library

For AWS CDK v1:

   ```sh
   pip install datadog-cdk-constructs
   ```

For AWS CDK v2:

   ```sh
   pip install datadog-cdk-constructs-v2
   ```

1. Instrument your Lambda functions

For AWS CDK v1:

   ```python
   from datadog_cdk_constructs import Datadog
   datadog = Datadog(self, "Datadog",
       dotnet_layer_version=23,
       extension_layer_version=94,
       site="<DATADOG_SITE>",
       api_key_secret_arn="<DATADOG_API_KEY_SECRET_ARN>",
     )
   datadog.add_lambda_functions([<LAMBDA_FUNCTIONS>])
   ```

For AWS CDK v2:

   ```python
   from datadog_cdk_constructs_v2 import DatadogLambda
   
   datadog = DatadogLambda(self, "datadogLambda",
       dotnet_layer_version=23,
       extension_layer_version=94,
       site="<DATADOG_SITE>",
       api_key_secret_arn="<DATADOG_API_KEY_SECRET_ARN>",
     )
   datadog.add_lambda_functions([<LAMBDA_FUNCTIONS>])
   ```

### Go{% #go %}

**Note**: Go CDK constructs are only available for AWS CDK v2.

1. Install the Datadog CDK constructs library

   ```sh
   go get github.com/DataDog/datadog-cdk-constructs-go/ddcdkconstruct/v3
   ```

1. Instrument your Lambda functions

   ```go
   import (
       "github.com/DataDog/datadog-cdk-constructs-go/ddcdkconstruct/v3"
   )
   
   datadogLambda := ddcdkconstruct.NewDatadogLambda(
       stack,
       jsii.String("Datadog"),
       &ddcdkconstruct.DatadogLambdaProps{
           DotnetLayerVersion:      jsii.Number(23),
           ExtensionLayerVersion: jsii.Number(94),
           Site:                  jsii.String("<DATADOG_SITE>"),
           ApiKeySecretArn:       jsii.String("<DATADOG_API_KEY_SECRET_ARN>"),
       })
   datadogLambda.AddLambdaFunctions(&[]interface{}{<LAMBDA_FUNCTIONS>}, nil)
   ```

To fill in the placeholders:

- Replace `<DATADOG_SITE>` with  (ensure the correct SITE is selected on the right).
- Replace `<DATADOG_API_KEY_SECRET_ARN>` with the ARN of the AWS secret where your [Datadog API key](https://app.datadoghq.com/organization-settings/api-keys) is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). Ensure your Lambda execution role has the `secretsmanager:GetSecretValue` IAM permission in order to read the secret value. For quick testing, you can use `apiKey` instead and set the Datadog API key in plaintext.

More information and additional parameters can be found on the [Datadog CDK documentation](https://github.com/DataDog/datadog-cdk-constructs).
{% /tab %}

{% tab title="Container image" %}

1. Install the Datadog Lambda Extension

   ```dockerfile
   COPY --from=public.ecr.aws/datadog/lambda-extension:<TAG> /opt/. /opt/
   ```

Replace `<TAG>` with either a specific version number (for example, `94`) or with `latest`. Alpine is also supported with specific version numbers (such as `94-alpine`) or with `latest-alpine`. You can see a complete list of possible tags in the [Amazon ECR repository](https://gallery.ecr.aws/datadog/lambda-extension).

1. Install the Datadog .NET APM client

   ```dockerfile
   RUN yum -y install tar wget gzip
   RUN wget https://github.com/DataDog/dd-trace-dotnet/releases/download/v<TRACER_VERSION>/datadog-dotnet-apm-<TRACER_VERSION>.tar.gz
   RUN mkdir /opt/datadog
   RUN tar -C /opt/datadog -xzf datadog-dotnet-apm-<TRACER_VERSION>.tar.gz
   ENV AWS_LAMBDA_EXEC_WRAPPER /opt/datadog_wrapper
   ```

Replace `<TRACER_VERSION>` with the version number of `dd-trace-dotnet` you would like to use (for example, `2.3.0`). The minimum supported version is `2.3.0`. You can see the latest versions of `dd-trace-dotnet` in [GitHub](https://github.com/DataDog/dd-trace-dotnet/releases).

1. Set the required environment variables

   - Set the environment variable `DD_SITE` to  (ensure the correct SITE is selected on the right).
   - Set the environment variable `DD_API_KEY_SECRET_ARN` with the ARN of the AWS secret where your [Datadog API key](https://app.datadoghq.com/organization-settings/api-keys) is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The `secretsmanager:GetSecretValue` permission is required. For quick testing, you can use `DD_API_KEY` instead and set the Datadog API key in plaintext.

{% /tab %}

{% tab title="Terraform" %}
The [`lambda-datadog`](https://registry.terraform.io/modules/DataDog/lambda-datadog/aws/latest) Terraform module wraps the [`aws_lambda_function`](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/lambda_function) resource and automatically configures your Lambda function for Datadog Serverless Monitoring by:

- Adding the Datadog Lambda layers
- Redirecting the Lambda handler
- Enabling the collection and sending of metrics, traces, and logs to Datadog

```tf
module "lambda-datadog" {
  source  = "DataDog/lambda-datadog/aws"
  version = "4.0.0"

  environment_variables = {
    "DD_API_KEY_SECRET_ARN" : "<DATADOG_API_KEY_SECRET_ARN>"
    "DD_ENV" : "<ENVIRONMENT>"
    "DD_SERVICE" : "<SERVICE_NAME>"
    "DD_SITE": "<DATADOG_SITE>"
    "DD_VERSION" : "<VERSION>"
  }

  datadog_extension_layer_version = 94
  datadog_dotnet_layer_version = 23

  # aws_lambda_function arguments
}
```

1. Replace the `aws_lambda_function` resource with the `lambda-datadog` Terraform module then specify the `source` and `version` of the module.

1. Set the `aws_lambda_function` arguments:

All of the arguments available in the `aws_lambda_function` resource are available in this Terraform module. Arguments defined as blocks in the `aws_lambda_function` resource are redefined as variables with their nested arguments.

For example, in `aws_lambda_function`, `environment` is defined as a block with a `variables` argument. In the `lambda-datadog` Terraform module, the value for the `environment_variables` is passed to the `environment.variables` argument in `aws_lambda_function`. See [inputs](https://github.com/DataDog/terraform-aws-lambda-datadog?tab=readme-ov-file#inputs) for a complete list of variables in this module.

1. Fill in the environment variable placeholders:

   - Replace `<DATADOG_API_KEY_SECRET_ARN>` with the ARN of the AWS secret where your Datadog API key is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The `secretsmanager:GetSecretValue` permission is required. For quick testing, you can instead use the environment variable `DD_API_KEY` and set your Datadog API key in plaintext.
   - Replace `<ENVIRONMENT>` with the Lambda function's environment, such as `prod` or `staging`
   - Replace `<SERVICE_NAME>` with the name of the Lambda function's service
   - Replace `<DATADOG_SITE>` with . (Ensure the correct [Datadog site](https://docs.datadoghq.com/getting_started/site/) is selected on this page).
   - Replace `<VERSION>` with the version number of the Lambda function

1. Select the versions of the Datadog Extension Lambda layer and Datadog .NET Lambda layer to use. Defaults to the latest layer versions.

```
  datadog_extension_layer_version = 94
  datadog_dotnet_layer_version = 23
```

{% /tab %}

{% tab title="Custom" %}

1. Install the Datadog Tracer

[Configure the layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) for your Lambda function using the ARN in the following format:

   ```sh
   # Use this format for x86-based Lambda deployed in AWS commercial regions
   arn:aws:lambda:<AWS_REGION>:464622532012:layer:dd-trace-dotnet:23
   
   # Use this format for arm64-based Lambda deployed in AWS commercial regions
   arn:aws:lambda:<AWS_REGION>:464622532012:layer:dd-trace-dotnet-ARM:23
   
   # Use this format for x86-based Lambda deployed in AWS GovCloud regions
   arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:dd-trace-dotnet:23
   
   # Use this format for arm64-based Lambda deployed in AWS GovCloud regions
   arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:dd-trace-dotnet-ARM:23
   ```

Replace `<AWS_REGION>` with a valid AWS region, such as `us-east-1`.

1. Install the Datadog Lambda Extension

[Configure the layers](https://docs.aws.amazon.com/lambda/latest/dg/configuration-layers.html) for your Lambda function using the ARN in the following format:

   ```sh
   # Use this format for x86-based Lambda deployed in AWS commercial regions
   arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-Extension:94
   
   # Use this format for arm64-based Lambda deployed in AWS commercial regions
   arn:aws:lambda:<AWS_REGION>:464622532012:layer:Datadog-Extension-ARM:94
   
   # Use this format for x86-based Lambda deployed in AWS GovCloud regions
   arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-Extension:94
   
   # Use this format for arm64-based Lambda deployed in AWS GovCloud regions
   arn:aws-us-gov:lambda:<AWS_REGION>:002406178527:layer:Datadog-Extension-ARM:94
   ```

Replace `<AWS_REGION>` with a valid AWS region, such as `us-east-1`.

1. Set the required environment variables

   - Set `AWS_LAMBDA_EXEC_WRAPPER` to `/opt/datadog_wrapper`.
   - Set `DD_SITE` to  (ensure the correct SITE is selected on the right).
   - Set `DD_API_KEY_SECRET_ARN` to the ARN of the AWS secret where your [Datadog API key](https://app.datadoghq.com/organization-settings/api-keys) is securely stored. The key needs to be stored as a plaintext string (not a JSON blob). The `secretsmanager:GetSecretValue` permission is required. For quick testing, you can use `DD_API_KEY` instead and set the Datadog API key in plaintext.

{% /tab %}

**Do not set** the following environment variables in your serverless environment. They should only be set in non-serverless environments.

- `DD_AGENT_HOST`
- `DD_TRACE_AGENT_URL`

## Add custom spans{% #add-custom-spans %}

When using the [Datadog Lambda tracing layer for .NET](https://github.com/DataDog/dd-trace-dotnet-aws-lambda-layer), ensure that a second version of the .NET tracer is not also packaged with your application code. Add the `ExcludeAssets` instruction to ensure this extra tracer is excluded.

```xml
<PackageReference Include="Datadog.Trace" Version="3.26.3"/>
```

You can then add custom spans and span tags using the .NET tracer. For instructions on how to add spans, see [.NET custom instrumentation](https://docs.datadoghq.com/tracing/trace_collection/custom_instrumentation/dotnet/dd-api/).

## FIPS compliance{% #fips-compliance %}

Datadog provides FIPS-compliant monitoring for AWS Lambda functions. For AWS GovCloud environments, the `DD_LAMBDA_FIPS_MODE` environment variable is enabled by default. When FIPS mode is enabled, AWS FIPS endpoints are used for Datadog API key lookups, and the Lambda metric helper function `lambda_metric` requires the FIPS-compliant extension for metric submission. While the FIPS-compliant Lambda components work with any Datadog site, end-to-end FIPS compliance requires using the US1-FED site. See [AWS Lambda FIPS Compliance](https://docs.datadoghq.com/serverless/aws_lambda/fips-compliance) for more details.

## AWS Lambda and VPC{% #aws-lambda-and-vpc %}

If your Lambda functions are deployed in a Virtual Private Cloud (VPC) without access to the public internet, and you are using the `datadoghq.com` [Datadog site](https://docs.datadoghq.com/getting_started/site/), you can [use AWS PrivateLink](https://docs.datadoghq.com/agent/guide/private-link/) to send data.

If your Lambda functions are deployed in a VPC, and you are using a [Datadog site](https://docs.datadoghq.com/getting_started/site/) that is **not** `datadoghq.com`, you can [use a proxy](https://docs.datadoghq.com/agent/configuration/proxy/) to send data.

- Add custom tags to your telemetry by using the `DD_TAGS` environment variable
- Configure [payload collection](https://docs.datadoghq.com/serverless/aws_lambda/configuration?tab=datadogcli#collect-the-request-and-response-payloads) to capture your functions' JSON request and response payloads
- If you are using the Datadog Lambda Extension, turn off the Datadog Forwarder's Lambda logs
- See [Configure Serverless Monitoring for AWS Lambda](https://docs.datadoghq.com/serverless/configuration/) for further capabilities

## Further Reading{% #further-reading %}

- [Configure Serverless Monitoring](https://docs.datadoghq.com/serverless/configuration)
- [Troubleshoot Serverless Monitoring](https://docs.datadoghq.com/serverless/guide/troubleshoot_serverless_monitoring)
- [Submitting Custom Metrics from Serverless Applications](https://docs.datadoghq.com/serverless/custom_metrics/)
