

# Improving startup performance with Lambda SnapStart
<a name="snapstart"></a>

Lambda SnapStart can provide as low as sub-second startup performance, typically with no changes to your function code. SnapStart makes it easier to build highly responsive and scalable applications without provisioning resources or implementing complex performance optimizations.

The largest contributor to startup latency (often referred to as cold start time) is the time that Lambda spends initializing the function, which includes loading the function's code, starting the runtime, and initializing the function code. With SnapStart, Lambda initializes your function when you publish a function version. Lambda takes a [Firecracker microVM](https://aws.amazon.com/blogs/opensource/firecracker-open-source-secure-fast-microvm-serverless/) snapshot of the memory and disk state of the initialized [execution environment](lambda-runtime-environment.md), encrypts the snapshot, and intelligently caches it to optimize retrieval latency.

To ensure resiliency, Lambda maintains several copies of each snapshot. Lambda automatically patches snapshots and their copies with the latest runtime and security updates. When you invoke the function version for the first time, and as the invocations scale up, Lambda resumes new execution environments from the cached snapshot instead of initializing them from scratch, improving startup latency.

**Important**  
If your applications depend on uniqueness of state, you must evaluate your function code and verify that it is resilient to snapshot operations. For more information, see [Handling uniqueness with Lambda SnapStart](snapstart-uniqueness.md).

**Topics**
+ [When to use SnapStart](#snapstart-use-cases)
+ [Supported features and limitations](#snapstart-runtimes)
+ [Supported Regions](#snapstart-supported-regions)
+ [Compatibility considerations](#snapstart-compatibility)
+ [SnapStart pricing](#snapstart-pricing)
+ [Activating and managing Lambda SnapStart](snapstart-activate.md)
+ [Handling uniqueness with Lambda SnapStart](snapstart-uniqueness.md)
+ [Implement code before or after Lambda function snapshots](snapstart-runtime-hooks.md)
+ [Monitoring for Lambda SnapStart](snapstart-monitoring.md)
+ [Security model for Lambda SnapStart](snapstart-security.md)
+ [Maximize Lambda SnapStart performance](snapstart-best-practices.md)
+ [Troubleshooting SnapStart errors for Lambda functions](snapstart-troubleshooting.md)

## When to use SnapStart
<a name="snapstart-use-cases"></a>

Lambda SnapStart is designed to address the latency variability introduced by one-time initialization code, such as loading module dependencies or frameworks. These operations can sometimes take several seconds to complete during the initial invocation. Use SnapStart to reduce this latency from several seconds to as low as sub-second, in optimal scenarios. SnapStart works best when used with function invocations at scale. Functions that are invoked infrequently might not experience the same performance improvements.

SnapStart is particularly beneficial for two main types of applications:
+ **Latency-sensitive APIs and user flows:** Functions that are part of critical API endpoints or user-facing flows can benefit from SnapStart's reduced latency and improved response times.
+ **Latency-sensitive data processing workflows:** Time-bound data processing workflows that use Lambda functions can achieve better throughput by reducing outlier function initialization latency.

[Provisioned concurrency](provisioned-concurrency.md) keeps functions initialized and ready to respond in double-digit milliseconds. Use provisioned concurrency if your application has strict cold start latency requirements that can't be adequately addressed by SnapStart.

## Supported features and limitations
<a name="snapstart-runtimes"></a>

SnapStart is available for the following [Lambda managed runtimes](lambda-runtimes.md):
+ Java 11 and later
+ Python 3.12 and later
+ .NET 8 and later. If you're using the [Lambda Annotations framework for .NET](csharp-handler.md#csharp-handler-annotations), upgrade to [Amazon.Lambda.Annotations](https://www.nuget.org/packages/Amazon.Lambda.Annotations) version 1.6.0 or later to ensure compatibility with SnapStart.

Other managed runtimes (such as `nodejs24.x` and `ruby3.4`), [OS-only runtimes](runtimes-provided.md), and [container images](images-create.md) are not supported.

SnapStart does not support [provisioned concurrency](provisioned-concurrency.md), [Amazon Elastic File System (Amazon EFS)](https://docs.aws.amazon.com/efs/latest/ug/accessing-fs.html), or ephemeral storage greater than 512 MB.

**Note**  
You can use SnapStart only on [published function versions](configuration-versions.md#configuration-versions-config) and [aliases](configuration-aliases.md) that point to versions. You can't use SnapStart on a function's unpublished version (\$1LATEST).

## Supported Regions
<a name="snapstart-supported-regions"></a>

Lambda SnapStart is available in all [commercial Regions](https://docs.aws.amazon.com/general/latest/gr/glos-chap.html#region) except Asia Pacific (New Zealand) and Asia Pacific (Taipei).

## Compatibility considerations
<a name="snapstart-compatibility"></a>

With SnapStart, Lambda uses a single snapshot as the initial state for multiple execution environments. If your function uses any of the following during the [initialization phase](lambda-runtime-environment.md#runtimes-lifecycle-ib), then you might need to make some changes before using SnapStart:

**Uniqueness**  
If your initialization code generates unique content that is included in the snapshot, then the content might not be unique when it is reused across execution environments. To maintain uniqueness when using SnapStart, you must generate unique content after initialization. This includes unique IDs, unique secrets, and entropy that's used to generate pseudorandomness. To learn how to restore uniqueness, see [Handling uniqueness with Lambda SnapStart](snapstart-uniqueness.md).

**Network connections**  
The state of connections that your function establishes during the initialization phase isn't guaranteed when Lambda resumes your function from a snapshot. Validate the state of your network connections and re-establish them as necessary. In most cases, network connections that an AWS SDK establishes automatically resume. For other connections, review the [best practices](snapstart-best-practices.md). 

**Temporary data**  
Some functions download or initialize ephemeral data, such as temporary credentials or cached timestamps, during the initialization phase. Refresh ephemeral data in the function handler before using it, even when not using SnapStart.

## SnapStart pricing
<a name="snapstart-pricing"></a>

**Note**  
For Java managed runtimes, there's no additional cost for SnapStart. You're charged based on the number of requests for your functions, the time that it takes your code to run, and the memory configured for your function.

The cost of using SnapStart includes the following:
+ **Caching:** For every function version that you publish with SnapStart enabled, you pay for the cost of caching and maintaining the snapshot. The price depends on the amount of [memory](configuration-memory.md) that you allocate to your function. You're charged for a minimum of 3 hours. You will continue to be charged as long as your function remains [active](snapstart-activate.md#snapstart-active). Use the [ListVersionsByFunction](https://docs.aws.amazon.com/lambda/latest/api/API_ListVersionsByFunction.html) API action to identify function versions, and then use [DeleteFunction](https://docs.aws.amazon.com/lambda/latest/api/API_DeleteFunction.html) to delete unused versions. To automatically delete unused function versions, see the [Lambda Version Cleanup](https://serverlessland.com/workflows/step-functions-lambda-version-cleanup) pattern on Serverless Land.
+ **Restoration:** Each time a function instance is restored from a snapshot, you pay a restoration charge. The price depends on the amount of memory you allocate to your function.

As with all Lambda functions, duration charges apply to code that runs in the function handler. For SnapStart functions, duration charges also apply to initialization code that's declared outside of the handler, the time it takes for the runtime to load, and any code that runs in a [runtime hook](snapstart-runtime-hooks.md). Duration is calculated from the time that your code begins running until it returns or otherwise ends, rounded up to the nearest 1 ms. Lambda maintains cached copies of your snapshot for resiliency and automatically applies software updates, such as runtime upgrades and security patches to them. Charges apply each time that Lambda re-runs your initialization code to apply software updates.

For more information about the cost of using SnapStart, see [AWS Lambda Pricing](https://aws.amazon.com/lambda/pricing/#SnapStart_Pricing).

# Activating and managing Lambda SnapStart
<a name="snapstart-activate"></a>

To use SnapStart, activate SnapStart on a new or existing Lambda function. Then, publish and invoke a function version.

**Topics**
+ [Activating SnapStart (console)](#snapshot-console)
+ [Activating SnapStart (AWS CLI)](#snapshot-cli)
+ [Activating SnapStart (API)](#snapshot-api)
+ [Lambda SnapStart and function states](#snapstart-function-states)
+ [Updating a snapshot](#update-snapshot)
+ [Using SnapStart with AWS SDKs](#snapstart-credentials)
+ [Using SnapStart with CloudFormation, AWS SAM, and AWS CDK](#snapstart-cfn-sam)
+ [Deleting snapshots](#snapshot-delete)

## Activating SnapStart (console)
<a name="snapshot-console"></a>

**To activate SnapStart for a function**

1. Open the [Functions page](https://console.aws.amazon.com/lambda/home#/functions) of the Lambda console.

1. Choose the name of a function.

1. Choose **Configuration**, and then choose **General configuration**.

1. On the **General configuration** pane, choose **Edit**.

1. On the **Edit basic settings** page, for **SnapStart**, choose **Published versions**.

1. Choose **Save**.

1. [Publish a function version](configuration-versions.md#configuration-versions-config). Lambda initializes your code, creates a snapshot of the initialized execution environment, and then caches the snapshot for low-latency access.

1. [Invoke the function version](configuration-versions.md#versioning-versions-using).

## Activating SnapStart (AWS CLI)
<a name="snapshot-cli"></a>

**To activate SnapStart for an existing function**

1. Update the function configuration by running the [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) command with the **--snap-start** option.

   ```
   aws lambda update-function-configuration \
     --function-name my-function \
     --snap-start ApplyOn=PublishedVersions
   ```

1. Publish a function version with the [publish-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-version.html) command.

   ```
   aws lambda publish-version \
     --function-name my-function
   ```

1. Confirm that SnapStart is activated for the function version by running the [get-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-function-configuration.html) command and specifying the version number. The following example specifies version 1.

   ```
   aws lambda get-function-configuration \
     --function-name my-function:1
   ```

   If the response shows that [OptimizationStatus](https://docs.aws.amazon.com/lambda/latest/api/API_SnapStartResponse.html) is `On` and [State](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State) is `Active`, then SnapStart is activated and a snapshot is available for the specified function version.

   ```
   "SnapStart": { 
       "ApplyOn": "PublishedVersions",
       "OptimizationStatus": "On"
    },
    "State": "Active",
   ```

1. Invoke the function version by running the [invoke](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/invoke.html) command and specifying the version. The following example invokes version 1.

   ```
   aws lambda invoke \
     --cli-binary-format raw-in-base64-out \
     --function-name my-function:1 \
     --payload '{ "name": "Bob" }' \
     response.json
   ```

   The **cli-binary-format** option is required if you're using AWS CLI version 2. To make this the default setting, run `aws configure set cli-binary-format raw-in-base64-out`. For more information, see [AWS CLI supported global command line options](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) in the *AWS Command Line Interface User Guide for Version 2*.

**To activate SnapStart when you create a new function**

1. Create a function by running the [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) command with the **--snap-start** option. For **--role**, specify the Amazon Resource Name (ARN) of your [execution role](lambda-intro-execution-role.md).

   ```
   aws lambda create-function \
     --function-name my-function \
     --runtime "java25" \
     --zip-file fileb://my-function.zip \
     --handler my-function.handler \
     --role arn:aws:iam::111122223333:role/lambda-ex \
     --snap-start ApplyOn=PublishedVersions
   ```

1. Create a version with the [publish-version](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/publish-version.html) command.

   ```
   aws lambda publish-version \
     --function-name my-function
   ```

1. Confirm that SnapStart is activated for the function version by running the [get-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/get-function-configuration.html) command and specifying the version number. The following example specifies version 1.

   ```
   aws lambda get-function-configuration \
     --function-name my-function:1
   ```

   If the response shows that [OptimizationStatus](https://docs.aws.amazon.com/lambda/latest/api/API_SnapStartResponse.html) is `On` and [State](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State) is `Active`, then SnapStart is activated and a snapshot is available for the specified function version.

   ```
   "SnapStart": { 
        "ApplyOn": "PublishedVersions",
        "OptimizationStatus": "On"
     },
     "State": "Active",
   ```

1. Invoke the function version by running the [invoke](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/invoke.html) command and specifying the version. The following example invokes version 1.

   ```
   aws lambda invoke \
     --cli-binary-format raw-in-base64-out \
     --function-name my-function:1 \
     --payload '{ "name": "Bob" }' \
     response.json
   ```

   The **cli-binary-format** option is required if you're using AWS CLI version 2. To make this the default setting, run `aws configure set cli-binary-format raw-in-base64-out`. For more information, see [AWS CLI supported global command line options](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-options.html#cli-configure-options-list) in the *AWS Command Line Interface User Guide for Version 2*.

## Activating SnapStart (API)
<a name="snapshot-api"></a>

**To activate SnapStart**

1. Do one of the following:
   + Create a new function with SnapStart activated by using the [CreateFunction](https://docs.aws.amazon.com/lambda/latest/api/API_CreateFunction.html) API action with the [SnapStart](https://docs.aws.amazon.com/lambda/latest/api/API_SnapStart.html) parameter.
   + Activate SnapStart for an existing function by using the [UpdateFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html) action with the [SnapStart](https://docs.aws.amazon.com/lambda/latest/api/API_SnapStart.html) parameter.

1. Publish a function version with the [PublishVersion](https://docs.aws.amazon.com/lambda/latest/api/API_PublishVersion.html) action. Lambda initializes your code, creates a snapshot of the initialized execution environment, and then caches the snapshot for low-latency access.

1. Confirm that SnapStart is activated for the function version by using the [GetFunctionConfiguration](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html) action. Specify a version number to confirm that SnapStart is activated for that version. If the response shows that [OptimizationStatus](https://docs.aws.amazon.com/lambda/latest/api/API_SnapStartResponse.html) is `On` and [State](https://docs.aws.amazon.com/lambda/latest/api/API_GetFunctionConfiguration.html#lambda-GetFunctionConfiguration-response-State) is `Active`, then SnapStart is activated and a snapshot is available for the specified function version.

   ```
   "SnapStart": { 
           "ApplyOn": "PublishedVersions",
           "OptimizationStatus": "On"
        },
        "State": "Active",
   ```

1. Invoke the function version with the [Invoke](https://docs.aws.amazon.com/lambda/latest/api/API_Invoke.html) action.

## Lambda SnapStart and function states
<a name="snapstart-function-states"></a>

The following function states can occur when you use SnapStart.

**Pending**  
Lambda is initializing your code and taking a snapshot of the initialized execution environment. Any invocations or other API actions that operate on the function version will fail.

**Active**  
Snapshot creation is complete and you can invoke the function. To use SnapStart, you must invoke the published function version, not the unpublished version (\$1LATEST).

**Inactive**  
The `Inactive` state can occur when Lambda periodically regenerates function snapshots to apply software updates. In this instance, if your function fails to initialize, the function can enter an `Inactive` state.  
For functions using a Java runtime, Lambda deletes snapshots after 14 days without an invocation. If you invoke the function version after 14 days, Lambda returns a `SnapStartNotReadyException` response and begins initializing a new snapshot. Wait until the function version reaches the `Active` state, and then invoke it again.

**Failed**  
Lambda encountered an error when running the initialization code or creating the snapshot.

## Updating a snapshot
<a name="update-snapshot"></a>

Lambda creates a snapshot for each published function version. To update a snapshot, publish a new function version.

## Using SnapStart with AWS SDKs
<a name="snapstart-credentials"></a>

To make AWS SDK calls from your function, Lambda generates an ephemeral set of credentials by assuming your function's execution role. These credentials are available as environment variables during your function's invocation. You don't need to provide credentials for the SDK directly in code. By default, the credential provider chain sequentially checks each place where you can set credentials and chooses the first available—usually the environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_SESSION_TOKEN`).

**Note**  
When SnapStart is activated, the Lambda runtime automatically uses the container credentials (`AWS_CONTAINER_CREDENTIALS_FULL_URI` and `AWS_CONTAINER_AUTHORIZATION_TOKEN`) instead of the access key environment variables. This prevents credentials from expiring before the function is restored.

## Using SnapStart with CloudFormation, AWS SAM, and AWS CDK
<a name="snapstart-cfn-sam"></a>
+ **AWS CloudFormation:** Declare the [SnapStart](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-function-snapstart.html) entity in your template.
+ **AWS Serverless Application Model (AWS SAM):** Declare the [SnapStart](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-resource-function.html#sam-function-snapstart) property in your template.
+ **AWS Cloud Development Kit (AWS CDK):** Use the [SnapStartProperty](https://docs.aws.amazon.com/cdk/api/v2/java/software/amazon/awscdk/services/lambda/CfnFunction.SnapStartProperty.html) type.

## Deleting snapshots
<a name="snapshot-delete"></a>

Lambda deletes snapshots when:
+ You delete the function or function version.
+ **Java runtimes only** — You don't invoke the function version for 14 days. After 14 days without an invocation, the function version transitions to the [Inactive](#snapstart-function-states) state. If you invoke the function version after 14 days, Lambda returns a `SnapStartNotReadyException` response and begins initializing a new snapshot. Wait until the function version reaches the [Active](#snapstart-function-states) state, and then invoke it again.

Lambda removes all resources associated with deleted snapshots in compliance with the General Data Protection Regulation (GDPR).

# Handling uniqueness with Lambda SnapStart
<a name="snapstart-uniqueness"></a>

When invocations scale up on a SnapStart function, Lambda uses a single initialized snapshot to resume multiple execution environments. If your initialization code generates unique content that is included in the snapshot, then the content might not be unique when it is reused across execution environments. To maintain uniqueness when using SnapStart, you must generate unique content after initialization. This includes unique IDs, unique secrets, and entropy that's used to generate pseudorandomness.

We recommend the following best practices to help you maintain uniqueness in your code. For Java functions, Lambda also provides an open-source [SnapStart scanning tool](#snapstart-scanning) to help check for code that assumes uniqueness. If you generate unique data during the initialization phase, then you can use a [runtime hook](snapstart-runtime-hooks.md) to restore uniqueness. With runtime hooks, you can run specific code immediately before Lambda takes a snapshot or immediately after Lambda resumes a function from a snapshot.

## Avoid saving state that depends on uniqueness during initialization
<a name="snapstart-caching-unique"></a>

During the [initialization phase](lambda-runtime-environment.md#runtimes-lifecycle-ib) of your function, avoid caching data that's intended to be unique, such as generating a unique ID for logging or setting seeds for random functions. Instead, we recommend that you generate unique data or set seeds for random functions inside your function handler—or use a [runtime hook](snapstart-runtime-hooks.md).

The following examples demonstrate how to generate a UUID in the function handler.

------
#### [ Java ]

**Example – Generating a unique ID in function handler**  

```
import java.util.UUID;
  public class Handler implements RequestHandler<String, String> {
    private static UUID uniqueSandboxId = null;
    @Override
    public String handleRequest(String event, Context context) {
      if (uniqueSandboxId == null)
        uniqueSandboxId = UUID.randomUUID();
      System.out.println("Unique Sandbox Id: " + uniqueSandboxId);
      return "Hello, World!";
    }
  }
```

------
#### [ Python ]

**Example – Generating a unique ID in function handler**  

```
import json
import random
import time

unique_number = None

def lambda_handler(event, context):
    seed = int(time.time() * 1000) 
    random.seed(seed)
    global unique_number
    if not unique_number:
        unique_number = random.randint(1, 10000)
        
    print("Unique number: ", unique_number)
    
    return "Hello, World!"
```

------
#### [ .NET ]

**Example – Generating a unique ID in function handler**  

```
namespace Example;
public class SnapstartExample
{
    private Guid _myExecutionEnvironmentGuid;
    public SnapstartExample()
    {
        // This GUID is set for non-restore use cases, such as testing or if SnapStart is turned off
        _myExecutionEnvironmentGuid = new Guid();
        // Register the method which will run after each restore. You may need to update Amazon.Lambda.Core to see this
        Amazon.Lambda.Core.SnapshotRestore.RegisterAfterRestore(MyAfterRestore);
    }

    private ValueTask MyAfterRestore()
    {
        // After restoring this snapshot to a new execution environment, update the GUID
        _myExecutionEnvironmentGuid = new Guid();
        return ValueTask.CompletedTask;
    }

    public string Handler()
    {
        return $"Hello World! My Execution Environment GUID is {_myExecutionEnvironmentGuid}";
    }
}
```

------

## Use cryptographically secure pseudorandom number generators (CSPRNGs)
<a name="snapstart-csprng"></a>

If your application depends on randomness, we recommend that you use cryptographically secure random number generators (CSPRNGs). In addition to OpenSSL 1.0.2, the Lambda managed runtimes also include the following built-in CSPRNGs:
+ **Java:** `java.security.SecureRandom`
+ **Python:** `random.SystemRandom`
+ **.NET:** `System.Security.Cryptography.RandomNumberGenerator`

Software that always gets random numbers from `/dev/random` or `/dev/urandom` also maintains randomness with SnapStart.

AWS cryptography libraries automatically maintain randomness with SnapStart beginning with the minimum versions specified in the following table. If you use these libraries with your Lambda functions, make sure that you use the following minimum versions or later versions:


****  

| Library | Minimum supported version (x86) | Minimum supported version (ARM) | 
| --- | --- | --- | 
| AWS libcrypto (AWS-LC) |  1.16.0  |  1.30.0  | 
| AWS libcrypto FIPS |  2.0.13  | 2.0.13 | 

If you package the preceding cryptographic libraries with your Lambda functions as transitive dependencies through the following libraries, make sure that you use the following minimum versions or later versions:


****  

| Library | Minimum supported version (x86) | Minimum supported version (ARM) | 
| --- | --- | --- | 
| AWS SDK for Java 2.x |  2.23.20  |  2.26.12  | 
| AWS Common Runtime for Java |  0.29.8  |  0.29.25  | 
| Amazon Corretto Crypto Provider |  2.4.1  | 2.4.1 | 
| Amazon Corretto Crypto Provider FIPS |  2.4.1  | 2.4.1 | 

The following examples demonstrate how to use CSPRNGs to guarantee unique number sequences even when the function is restored from a snapshot.

------
#### [ Java ]

**Example – java.security.SecureRandom**  

```
import java.security.SecureRandom;
  public class Handler implements RequestHandler<String, String> {
    private static SecureRandom rng = new SecureRandom();
    @Override
    public String handleRequest(String event, Context context) {
      for (int i = 0; i < 10; i++) {
        System.out.println(rng.next());
      }
      return "Hello, World!";
    }
  }
```

------
#### [ Python ]

**Example – random.SystemRandom**  

```
import json
import random

secure_rng = random.SystemRandom()

def lambda_handler(event, context):
    random_numbers = [secure_rng.random() for _ in range(10)]
    
    for number in random_numbers:
        print(number)
    
    return "Hello, World!"
```

------
#### [ .NET ]

**Example – RandomNumberGenerator**  

```
using Amazon.Lambda.Core;
using System.Security.Cryptography;
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace DotnetSecureRandom;

public class Function
{
    public string FunctionHandler()
    {
        using (RandomNumberGenerator rng = RandomNumberGenerator.Create())
        {
            byte[] randomUnsignedInteger32Bytes = new byte[4];
            for (int i = 0; i < 10; i++)
            {
                rng.GetBytes(randomUnsignedInteger32Bytes);
                int randomInt32 = BitConverter.ToInt32(randomUnsignedInteger32Bytes, 0);
                Console.WriteLine("{0:G}", randomInt32);
            }
        }
        return "Hello World!";
    }
}
```

------

## SnapStart scanning tool (Java only)
<a name="snapstart-scanning"></a>

Lambda provides a scanning tool for Java to help you check for code that assumes uniqueness. The SnapStart scanning tool is an open-source [SpotBugs](https://spotbugs.github.io/) plugin that runs a static analysis against a set of rules. The scanning tool helps identify potential code implementations that might break assumptions regarding uniqueness. For installation instructions and a list of checks that the scanning tool performs, see the [aws-lambda-snapstart-java-rules](https://github.com/aws/aws-lambda-snapstart-java-rules) repository on GitHub.

To learn more about handling uniqueness with SnapStart, see [Starting up faster with AWS Lambda SnapStart](https://aws.amazon.com/blogs/compute/starting-up-faster-with-aws-lambda-snapstart/) on the AWS Compute Blog.

# Implement code before or after Lambda function snapshots
<a name="snapstart-runtime-hooks"></a>

You can use runtime hooks to implement code before Lambda creates a snapshot or after Lambda resumes a function from a snapshot. Runtime hooks are useful for a variety of purposes, such as:
+ **Cleanup and initialization:** Before a snapshot is created, you can use a runtime hook to perform cleanup or resource release operations. After a snapshot is restored, you can use a runtime hook to re-initialize any resources or state that were not captured in the snapshot.
+ **Dynamic configuration:** You can use runtime hooks to dynamically update configuration or other metadata before a snapshot is created or after it is restored. This can be useful if your function needs to adapt to changes in the runtime environment.
+ **External integrations:** You can use runtime hooks to integrate with external services or systems, such as sending notifications or updating external state, as part of the checkpointing and restoration process.
+ **Performance tuning:** You can use runtime hooks to fine-tune your function's startup sequence, such as by preloading dependencies. For more information, see [Performance tuning](snapstart-best-practices.md#snapstart-tuning).

The following pages explain how to implement runtime hooks for your preferred runtime.

**Topics**
+ [Java](snapstart-runtime-hooks-java.md)
+ [Python](snapstart-runtime-hooks-python.md)
+ [.NET](snapstart-runtime-hooks-dotnet.md)

# Lambda SnapStart runtime hooks for Java
<a name="snapstart-runtime-hooks-java"></a>

You can use runtime hooks to implement code before Lambda creates a snapshot or after Lambda resumes a function from a snapshot. Runtime hooks are available as part of the open-source Coordinated Restore at Checkpoint (CRaC) project. CRaC is in development for the [Open Java Development Kit (OpenJDK)](https://wiki.openjdk.org/display/crac). For an example of how to use CRaC with a reference application, see the [CRaC](https://github.com/CRaC/docs/blob/master/STEP-BY-STEP.md) repository on GitHub. CRaC uses three main elements:
+ `Resource` – An interface with two methods, `beforeCheckpoint()` and `afterRestore()`. Use these methods to implement the code that you want to run before a snapshot and after a restore.
+ `Context <R extends Resource>` – To receive notifications for checkpoints and restores, a `Resource` must be registered with a `Context`.
+ `Core` – The coordination service, which provides the default global `Context` via the static method `Core.getGlobalContext()`.

For more information about `Context` and `Resource`, see [Package org.crac](https://javadoc.io/doc/io.github.crac/org-crac/latest/index.html) in the CRaC documentation.

Use the following steps to implement runtime hooks with the [org.crac package](https://github.com/CRaC/org.crac). The Lambda runtime contains a customized CRaC context implementation that calls your runtime hooks before checkpointing and after restoring.

## Runtime hook registration and execution
<a name="runtime-hooks-registration-java"></a>

The order that Lambda executes your runtime hooks is determined by the order of registration. Registration order follows the order of import, definition, or execution in your code.
+ `beforeCheckpoint()`: Executed in the reverse order of registration
+ `afterRestore()`: Executed in the order of registration

Make sure that all registered hooks are properly imported and included in your function's code. If you register runtime hooks in a separate file or module, you must ensure that the module is imported, either directly or as part of a larger package, in your function's handler file. If the file or module is not imported in the function handler, Lambda ignores the runtime hooks.

**Note**  
When Lambda creates a snapshot, your initialization code can run for up to 15 minutes. The time limit is 130 seconds or the [configured function timeout](configuration-timeout.md) (maximum 900 seconds), whichever is higher. Your `beforeCheckpoint()` runtime hooks count towards the initialization code time limit. When Lambda restores a snapshot, the runtime must load and `afterRestore()` runtime hooks must complete within the timeout limit (10 seconds). Otherwise, you'll get a SnapStartTimeoutException.

## Step 1: Update the build configuration
<a name="runtime-hooks-java-update-build"></a>

Add the `org.crac` dependency to the build configuration. The following example uses Gradle. For examples for other build systems, see the [Apache Maven documentation](https://search.maven.org/artifact/io.github.crac/org-crac/0.1.3/jar).

```
dependencies {
    compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.1'
    # All other project dependecies go here:
    # ...
    # Then, add the org.crac dependency:
 implementation group: 'org.crac', name: 'crac', version: '1.4.0'
}
```

## Step 2: Update the Lambda handler
<a name="runtime-hooks-java-update-handler"></a>

The Lambda function *handler* is the method in your function code that processes events. When your function is invoked, Lambda runs the handler method. Your function runs until the handler returns a response, exits, or times out.

For more information, see [Define Lambda function handler in Java](java-handler.md).

The following example handler shows how to run code before checkpointing (`beforeCheckpoint()`) and after restoring (`afterRestore()`). This handler also registers the `Resource` to the runtime-managed global `Context`.

**Note**  
When Lambda creates a snapshot, your initialization code can run for up to 15 minutes. The time limit is 130 seconds or the [configured function timeout](configuration-timeout.md) (maximum 900 seconds), whichever is higher. Your `beforeCheckpoint()` runtime hooks count towards the initialization code time limit. When Lambda restores a snapshot, the runtime (JVM) must load and `afterRestore()` runtime hooks must complete within the timeout limit (10 seconds). Otherwise, you'll get a SnapStartTimeoutException.

```
...
  import org.crac.Resource;
  import org.crac.Core;
  ... 
public class CRaCDemo implements RequestStreamHandler, Resource {
    public CRaCDemo() {
      Core.getGlobalContext().register(this);
    }
    public String handleRequest(String name, Context context) throws IOException {
      System.out.println("Handler execution");
      return "Hello " + name;
    }
    @Override
    public void beforeCheckpoint(org.crac.Context<? extends Resource> context)
        throws Exception {
      System.out.println("Before checkpoint");
    }
    @Override
    public void afterRestore(org.crac.Context<? extends Resource> context)
        throws Exception {
      System.out.println("After restore");
```

`Context` maintains only a [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/WeakReference.html](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/WeakReference.html) to the registered object. If a [https://javadoc.io/static/io.github.crac/org-crac/0.1.3/org/crac/Resource.html](https://javadoc.io/static/io.github.crac/org-crac/0.1.3/org/crac/Resource.html) is garbage collected, runtime hooks do not run. Your code must maintain a strong reference to the `Resource` to guarantee that the runtime hook runs.

Here are two examples of patterns to avoid:

**Example – Object without a strong reference**  

```
Core.getGlobalContext().register( new MyResource() );
```

**Example – Objects of anonymous classes**  

```
Core.getGlobalContext().register( new Resource() {
   
   @Override
   public void afterRestore(Context<? extends Resource> context) throws Exception {
    // ...
   }
   
   @Override
   public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
    // ...
   }

} );
```

Instead, maintain a strong reference. In the following example, the registered resource isn't garbage collected and runtime hooks run consistently.

**Example – Object with a strong reference**  

```
Resource myResource = new MyResource(); // This reference must be maintained to prevent the registered resource from being garbage collected
Core.getGlobalContext().register( myResource );
```

# Lambda SnapStart runtime hooks for Python
<a name="snapstart-runtime-hooks-python"></a>

You can use runtime hooks to implement code before Lambda creates a snapshot or after Lambda resumes a function from a snapshot. Python runtime hooks are available as part of the open-source [Snapshot Restore for Python library](https://pypi.org/project/snapshot-restore-py/), which is included in Python managed runtimes. This library provides two decorators that you can use to define your runtime hooks:
+ `@register_before_snapshot`: For functions you want to run before Lambda creates a snapshot.
+ `@register_after_restore`: For functions you want to run when Lambda resumes a function from a snapshot.

Alternatively, you can use the following methods to register callables for runtime hooks:
+ `register_before_snapshot(func, *args, **kwargs)`
+ `register_after_restore(func, *args, **kwargs)`

## Runtime hook registration and execution
<a name="runtime-hooks-registration-python"></a>

The order that Lambda executes your runtime hooks is determined by the order of registration:
+ Before snapshot: Executed in the reverse order of registration
+ After snapshot: Executed in the order of registration

The order of runtime hook registration depends on how you define the hooks. When using decorators (`@register_before_snapshot` and `@register_after_restore`), the registration order follows the order of import, definition, or execution in your code. If you need more control over the registration order, use the `register_before_snapshot()` and `register_after_restore()` methods instead of decorators.

Make sure that all registered hooks are properly imported and included in your function's code. If you register runtime hooks in a separate file or module, you must ensure that the module is imported, either directly or as part of a larger package, in your function's handler file. If the file or module is not imported in the function handler, Lambda ignores the runtime hooks.

**Note**  
When Lambda creates a snapshot, your initialization code can run for up to 15 minutes. The time limit is 130 seconds or the [configured function timeout](configuration-timeout.md) (maximum 900 seconds), whichever is higher. Your `@register_before_snapshot` runtime hooks count towards the initialization code time limit. When Lambda restores a snapshot, the runtime must load and `@register_after_restore` runtime hooks must complete within the timeout limit (10 seconds). Otherwise, you'll get a SnapStartTimeoutException.

## Example
<a name="runtime-hooks-python-code-sample"></a>

The following example handler shows how to run code before checkpointing (`@register_before_snapshot`) and after restoring (`@register_after_restore`).

```
from snapshot_restore_py import register_before_snapshot, register_after_restore

def lambda_handler(event, context):
    # Handler code

@register_before_snapshot
def before_checkpoint():
    # Logic to be executed before taking snapshots

@register_after_restore
def after_restore():
    # Logic to be executed after restore
```

For more examples, see [Snapshot Restore for Python](https://github.com/aws/snapshot-restore-py/tree/main/examples) in the AWS GitHub repository.

# Lambda SnapStart runtime hooks for .NET
<a name="snapstart-runtime-hooks-dotnet"></a>

You can use runtime hooks to implement code before Lambda creates a snapshot or after Lambda resumes a function from a snapshot. .NET runtime hooks are available as part of the [Amazon.Lambda.Core](https://www.nuget.org/packages/Amazon.Lambda.Core) package (version 2.5.0 or later). This library provides two methods that you can use to define your runtime hooks:
+ `RegisterBeforeSnapshot()`: Code to run before snapshot creation
+ `RegisterAfterSnapshot()`: Code to run after resuming a function from a snapshot

**Note**  
If you're using the [Lambda Annotations framework for .NET](csharp-handler.md#csharp-handler-annotations), upgrade to [Amazon.Lambda.Annotations](https://www.nuget.org/packages/Amazon.Lambda.Annotations) version 1.6.0 or later to ensure compatibility with SnapStart.

## Runtime hook registration and execution
<a name="runtime-hooks-registration-dotnet"></a>

Register your hooks in your initialization code. Consider the following guidelines based on your Lambda function's [execution model](csharp-handler.md#csharp-handler-setup):
+ For the [executable assembly approach](csharp-handler.md#csharp-executable-assembly-handlers), register your hooks before you start the Lambda bootstrap with `RunAsync`.
+ For the [class library approach](csharp-handler.md#csharp-class-library-handlers), register your hooks in the handler class constructor.
+ For [ASP.NET Core applications](csharp-package-asp.md), register your hooks before calling the `WebApplications.Run` method.

To register runtime hooks for SnapStart in .NET, use the following methods:

```
Amazon.Lambda.Core.SnapshotRestore.RegisterBeforeSnapshot(BeforeCheckpoint);
Amazon.Lambda.Core.SnapshotRestore.RegisterAfterRestore(AfterCheckpoint);
```

When multiple hook types are registered, the order that Lambda executes your runtime hooks is determined by the order of registration:
+ `RegisterBeforeSnapshot()`: Executed in the reverse order of registration
+ `RegisterAfterSnapshot()`: Executed in the order of registration

**Note**  
When Lambda creates a snapshot, your initialization code can run for up to 15 minutes. The time limit is 130 seconds or the [configured function timeout](configuration-timeout.md) (maximum 900 seconds), whichever is higher. Your `RegisterBeforeSnapshot()` runtime hooks count towards the initialization code time limit. When Lambda restores a snapshot, the runtime must load and `RegisterAfterSnapshot()` runtime hooks must complete within the timeout limit (10 seconds). Otherwise, you'll get a SnapStartTimeoutException.

## Example
<a name="runtime-hooks-dotnet-code-sample"></a>

The following example function shows how to run code before checkpointing (`RegisterBeforeSnapshot`) and after restoring (`RegisterAfterRestore`).

```
public class SampleClass
{
    public SampleClass()
    {
        Amazon.Lambda.Core.SnapshotRestore.RegisterBeforeSnapshot(BeforeCheckpoint);
        Amazon.Lambda.Core.SnapshotRestore.RegisterAfterRestore(AfterCheckpoint);
    }

    private ValueTask BeforeCheckpoint()
    {
        // Add logic to be executed before taking the snapshot
        return ValueTask.CompletedTask;
    }

    private ValueTask AfterCheckpoint()
    {
        // Add logic to be executed after restoring the snapshot
        return ValueTask.CompletedTask;
    }

    public APIGatewayProxyResponse FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
    {
        // Add business logic

        return new APIGatewayProxyResponse
        {
            StatusCode = 200
        };
    }
}
```

# Monitoring for Lambda SnapStart
<a name="snapstart-monitoring"></a>

You can monitor your Lambda SnapStart functions using Amazon CloudWatch, AWS X-Ray, and the [Accessing real-time telemetry data for extensions using the Telemetry API](telemetry-api.md).

**Note**  
The `AWS_LAMBDA_LOG_GROUP_NAME` and `AWS_LAMBDA_LOG_STREAM_NAME` [environment variables](configuration-envvars.md#configuration-envvars-runtime) are not available in Lambda SnapStart functions.

## Understanding logging and billing behavior with SnapStart
<a name="snapstart-cloudwatch"></a>

There are a few differences with the [CloudWatch log stream](monitoring-cloudwatchlogs.md) format for SnapStart functions:
+ **Initialization logs** – When a new execution environment is created, the `REPORT` doesn't include the `Init Duration` field. That's because Lambda initializes SnapStart functions when you create a version instead of during function invocation. For SnapStart functions, the `Init Duration` field is in the `INIT_REPORT` record. This record shows duration details for the [Init phase](lambda-runtime-environment.md#runtimes-lifecycle-ib), including the duration of any `beforeCheckpoint` [runtime hooks](snapstart-runtime-hooks.md).
+ **Invocation logs** – When a new execution environment is created, the `REPORT` includes the `Restore Duration` and `Billed Restore Duration` fields:
  + `Restore Duration`: The time it takes for Lambda to restore a snapshot, load the runtime, and run any after-restore [runtime hooks](snapstart-runtime-hooks.md). The process of restoring snapshots can include time spent on activities outside the MicroVM. This time is reported in `Restore Duration`.
  + `Billed Restore Duration`: The time it takes for Lambda to load the runtime and run any after-restore [runtime hooks](snapstart-runtime-hooks.md).

**Note**  
As with all Lambda functions, duration charges apply to code that runs in the function handler. For SnapStart functions, duration charges also apply to initialization code that's declared outside of the handler, the time it takes for the runtime to load, and any code that runs in a [runtime hook](snapstart-runtime-hooks.md).

The cold start duration is the sum of `Restore Duration` \$1 `Duration`.

The following example is a Lambda Insights query that returns the latency percentiles for SnapStart functions. For more information about Lambda Insights queries, see [Example workflow using queries to troubleshoot a function](monitoring-insights.md#monitoring-insights-queries).

```
filter @type = "REPORT"
  | parse @log /\d+:\/aws\/lambda\/(?<function>.*)/
  | parse @message /Restore Duration: (?<restoreDuration>.*?) ms/
  | stats
count(*) as invocations,
pct(@duration+coalesce(@initDuration,0)+coalesce(restoreDuration,0), 50) as p50,
pct(@duration+coalesce(@initDuration,0)+coalesce(restoreDuration,0), 90) as p90,
pct(@duration+coalesce(@initDuration,0)+coalesce(restoreDuration,0), 99) as p99,
pct(@duration+coalesce(@initDuration,0)+coalesce(restoreDuration,0), 99.9) as p99.9
group by function, (ispresent(@initDuration) or ispresent(restoreDuration)) as coldstart
  | sort by coldstart desc
```

## X-Ray active tracing for SnapStart
<a name="snapstart-xray"></a>

You can use [X-Ray](services-xray.md) to trace requests to Lambda SnapStart functions. There are a few differences with the X-Ray subsegments for SnapStart functions:
+ There is no `Initialization` subsegment for SnapStart functions.
+ The `Restore` subsegment shows the time it takes for Lambda to restore a snapshot, load the runtime, and run any after-restore [ runtime hooks](snapstart-runtime-hooks.md). The process of restoring snapshots can include time spent on activities outside the MicroVM. This time is reported in the `Restore` subsegment. You aren't charged for the time spent outside the microVM to restore a snapshot.

## Telemetry API events for SnapStart
<a name="snapstart-telemetry"></a>

Lambda sends the following SnapStart events to the [Telemetry API](telemetry-api.md):
+ [`platform.restoreStart`](telemetry-schema-reference.md#platform-restoreStart) – Shows the time when the [`Restore` phase](lambda-runtime-environment.md#runtimes-lifecycle-restore) started.
+ [`platform.restoreRuntimeDone`](telemetry-schema-reference.md#platform-restoreRuntimeDone) – Shows whether the `Restore` phase was successful. Lambda sends this message when the runtime sends a `restore/next` runtime API request. There are three possible statuses: success, failure, and timeout.
+ [`platform.restoreReport`](telemetry-schema-reference.md#platform-restoreReport) – Shows how long the `Restore` phase lasted and how many milliseconds you were billed for during this phase.

## Amazon API Gateway and function URL metrics
<a name="snapstart-metrics"></a>

If you create a web API [using API Gateway](services-apigateway.md), then you can use the [IntegrationLatency](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-metrics-and-dimensions.html) metric to measure end-to-end latency (the time between when API Gateway relays a request to the backend and when it receives a response from the backend).

If you're using a [Lambda function URL](urls-configuration.md), then you can use the [UrlRequestLatency](urls-monitoring.md) metric to measure end-to-end latency (the time between when the function URL receives a request and when the function URL returns a response).

# Security model for Lambda SnapStart
<a name="snapstart-security"></a>

Lambda SnapStart supports encryption at rest. Lambda encrypts snapshots with an AWS KMS key. By default, Lambda uses an AWS managed key. If this default behavior suits your workflow, then you don't need to set up anything else. Otherwise, you can use the `--kms-key-arn` option in the [create-function](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/create-function.html) or [update-function-configuration](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/lambda/update-function-configuration.html) command to provide an AWS KMS customer managed key. You might do this to control rotation of the KMS key or to meet the requirements of your organization for managing KMS keys. Customer managed keys incur standard AWS KMS charges. For more information, see [AWS Key Management Service pricing](https://aws.amazon.com/kms/pricing/).

When you delete a SnapStart function or function version, all `Invoke` requests to that function or function version fail. Lambda removes all resources associated with deleted snapshots in compliance with the General Data Protection Regulation (GDPR).

# Maximize Lambda SnapStart performance
<a name="snapstart-best-practices"></a>

**Topics**
+ [Performance tuning](#snapstart-tuning)
+ [Networking best practices](#snapstart-networking)

## Performance tuning
<a name="snapstart-tuning"></a>

To maximize the benefits of SnapStart, consider the following code optimization recommendations for your runtime.

**Note**  
SnapStart works best when used with function invocations at scale. Functions that are invoked infrequently might not experience the same performance improvements.

### Java
<a name="snapstart-tuning-java"></a>

To maximize the benefits of SnapStart, we recommend that you preload dependencies and initialize resources that contribute to startup latency in your initialization code instead of in the function handler. This moves the latency associated with heavy class loading out of the invocation path, optimizing startup performance with SnapStart.

If you can't preload dependencies or resources during initialization, then we recommend that you preload them with dummy invocations. To do this, update the function handler code, as shown in the following example from the [pet store function](https://github.com/awslabs/aws-serverless-java-container/tree/main/samples/spring/pet-store) on the AWS Labs GitHub repository.

```
private static SpringLambdaContainerHandler<AwsProxyRequest, AwsProxyResponse> handler;
  static {
      try {
          handler = SpringLambdaContainerHandler.getAwsProxyHandler(PetStoreSpringAppConfig.class);

          // Use the onStartup method of the handler to register the custom filter
          handler.onStartup(servletContext -> {
              FilterRegistration.Dynamic registration = servletContext.addFilter("CognitoIdentityFilter", CognitoIdentityFilter.class);
              registration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/*");
          });

          // Send a fake Amazon API Gateway request to the handler to load classes ahead of time
          ApiGatewayRequestIdentity identity = new ApiGatewayRequestIdentity();
          identity.setApiKey("foo");
          identity.setAccountId("foo");
          identity.setAccessKey("foo");

          AwsProxyRequestContext reqCtx = new AwsProxyRequestContext();
          reqCtx.setPath("/pets");
          reqCtx.setStage("default");
          reqCtx.setAuthorizer(null);
          reqCtx.setIdentity(identity);

          AwsProxyRequest req = new AwsProxyRequest();
          req.setHttpMethod("GET");
          req.setPath("/pets");
          req.setBody("");
          req.setRequestContext(reqCtx);

          Context ctx = new TestContext();
          handler.proxy(req, ctx);


      } catch (ContainerInitializationException e) {
          // if we fail here. We re-throw the exception to force another cold start
          e.printStackTrace();
          throw new RuntimeException("Could not initialize Spring framework", e);
      }
  }
```

### Python
<a name="snapstart-tuning-python"></a>

To maximize the benefits of SnapStart, focus on efficient code organization and resource management within your Python functions. As a general guideline, perform heavy computational tasks during the [initialization phase](lambda-runtime-environment.md#runtimes-lifecycle-ib). This approach moves time-consuming operations out of the invocation path, improving overall function performance. To implement this strategy effectively, we recommend the following best practices:
+ Import dependencies outside of the function handler.
+ Create `boto3` instances outside of the handler.
+ Initialize static resources or configurations before the handler is invoked.
+ Consider using a before-snapshot [runtime hook](snapstart-runtime-hooks-python.md) for resource-intensive tasks such as downloading external files, pre-loading frameworks like Django, or loading machine learning models.

**Example — Optimize Python function for SnapStart**  

```
# Import all dependencies outside of Lambda handler
from snapshot_restore_py import register_before_snapshot
import boto3
import pandas
import pydantic

# Create S3 and SSM clients outside of Lambda handler
s3_client = boto3.client("s3")

# Register the function to be called before snapshot
@register_before_snapshot
def download_llm_models():
    # Download an object from S3 and save to tmp
    # This files will persist in this snapshot
    with open('/tmp/FILE_NAME', 'wb') as f:
        s3_client.download_fileobj('amzn-s3-demo-bucket', 'OBJECT_NAME', f)
    ...

def lambda_handler(event, context):
    ...
```

### .NET
<a name="snapstart-tuning-dotnet"></a>

To reduce just-in-time (JIT) compilation and assembly loading time, consider invoking your function handler from a `RegisterBeforeCheckpoint` [runtime hook](snapstart-runtime-hooks-dotnet.md). Because of how .NET tiered compilation works, you’ll get optimal results by invoking the handler multiple times, as shown in the following example.

**Important**  
Make sure that your dummy function invocation does not produce unintended side effects, such as initiating business transactions.

**Example**  

```
public class Function
{
    public Function()
    {
        Amazon.Lambda.Core.SnapshotRestore.RegisterBeforeSnapshot(FunctionWarmup);
    }

    // Warmup method that calls the function handler before snapshot to warm up the .NET code and runtime.
    // This speeds up future cold starts after restoring from a snapshot.

    private async ValueTask FunctionWarmup()
    {
        var request = new APIGatewayProxyRequest
        {
            Path = "/heathcheck",
            HttpMethod = "GET"
        };

        for (var i = 0; i < 10; i++)
        {
            await FunctionHandler(request, null);
        }
    }

    public async Task<APIGatewayProxyResponse> FunctionHandler(APIGatewayProxyRequest request, ILambdaContext context)
    {
        //
        // Process HTTP request
        // 

        var response = new APIGatewayProxyResponse
        {
            StatusCode = 200
        };
        
        return await Task.FromResult(response);
    }
}
```

## Networking best practices
<a name="snapstart-networking"></a>

The state of connections that your function establishes during the initialization phase isn't guaranteed when Lambda resumes your function from a snapshot. In most cases, network connections that an AWS SDK establishes automatically resume. For other connections, we recommend the following best practices.

**Re-establish network connections**  
Always re-establish your network connections when your function resumes from a snapshot. We recommend that you re-establish network connections in the function handler. Alternatively, you can use an after-restore [runtime hook](snapstart-runtime-hooks.md).

**Don't use hostname as a unique execution environment identifier**  
We recommend against using `hostname` to identify your execution environment as a unique node or container in your applications. With SnapStart, a single snapshot is used as the initial state for multiple execution environments. All execution environments return the same `hostname` value for `InetAddress.getLocalHost()` (Java), `socket.gethostname()` (Python), and `Dns.GetHostName()` (.NET). For applications that require a unique execution environment identity or `hostname` value, we recommend that you generate a unique ID in the function handler. Or, use an after-restore [runtime hook](snapstart-runtime-hooks.md) to generate a unique ID, and then use the unique ID as the identifier for the execution environment.

**Avoid binding connections to fixed source ports**  
We recommend that you avoid binding network connections to fixed source ports. Connections are re-established when a function resumes from a snapshot, and network connections that are bound to a fixed source port might fail.

**Avoid using Java DNS cache**  
Lambda functions already cache DNS responses. If you use another DNS cache with SnapStart, then you might experience connection timeouts when the function resumes from a snapshot.

The `java.util.logging.Logger` class can indirectly enable the JVM DNS cache. To override the default settings, set [networkaddress.cache.ttl](https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/net/InetAddress.html#inetaddress-caching-heading) to 0 before initializing `logger`. Example:

```
public class MyHandler {
  // first set TTL property
  static{
   java.security.Security.setProperty("networkaddress.cache.ttl" , "0");
  }
 // then instantiate logger
  var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class);
}
```

To prevent `UnknownHostException` failures in the Java 11 runtime, we recommend setting `networkaddress.cache.negative.ttl` to 0. In Java 17 and later runtimes, this step isn't necessary. You can set this property for a Lambda function with the `AWS_LAMBDA_JAVA_NETWORKADDRESS_CACHE_NEGATIVE_TTL=0` environment variable.

Disabling the JVM DNS cache does not disable Lambda's managed DNS caching.

# Troubleshooting SnapStart errors for Lambda functions
<a name="snapstart-troubleshooting"></a>

This page addresses common issues that occur when using Lambda SnapStart, including snapshot creation errors, timeout errors, and internal service errors.

## SnapStartNotReadyException
<a name="snapstartnotreadyexception"></a>

**Error:** An error occurred (SnapStartNotReadyException) when calling the Invoke20150331 operation: Lambda is initializing your function. It will be ready to invoke once your function state becomes ACTIVE.

### Common causes
<a name="snapstartnotreadyexception-cause"></a>

This error occurs when you try to invoke a function version that is in the `Inactive` [state](snapstart-activate.md#snapstart-function-states). Your function version becomes `Inactive` when it hasn't been invoked for 14 days or when Lambda periodically recycles the execution environment

### Resolution
<a name="snapstartnotreadyexception-resolution"></a>

Wait until the function version reaches the `Active` state, and then invoke it again.

## SnapStartTimeoutException
<a name="snapstart-invocation-failure"></a>

**Issue:** You receive a `SnapStartTimeoutException` when you try to invoke a SnapStart function version.

### Common cause
<a name="snapstart-invocation-failure-cause"></a>

During the [Restore](lambda-runtime-environment.md#runtimes-lifecycle-restore) phase, Lambda restores the Java runtime and runs any after-restore [runtime hooks](snapstart-runtime-hooks.md). If an after-restore runtime hook runs for longer than 10 seconds, the `Restore` phase times out and you get an error when you try to invoke the function. Network connection and credentials issues can also cause `Restore` phase timeouts.

### Resolution
<a name="snapstart-invocation-failure-resolution"></a>

Check the function's CloudWatch logs for timeout errors that happened during the [Restore](lambda-runtime-environment.md#runtimes-lifecycle-restore) phase. Make sure that all after-restore hooks complete in less than 10 seconds.

**Example CloudWatch log**  

```
{ "cause": "Lambda couldn't restore the snapshot within the timeout limit. (Service: Lambda, Status Code: 408, Request ID: 11a222c3-410f-427c-ab22-931d6bcbf4f2)", "error": "Lambda.SnapStartTimeoutException"}
```

## 500 Internal Service Error
<a name="snapstart-500-error"></a>

**Error:** Lambda was unable to create a new snapshot because you have reached your concurrent snapshot creation limit.

### Common cause
<a name="snapstart-500-error-cause"></a>

A 500 error is an internal error within the Lambda service itself, rather than an issue with your function or code. These errors are often intermittent.

### Resolution
<a name="snapstart-500-error-resolution"></a>

Try to publish the function version again.

## 401 Unauthorized
<a name="snapstart-401-unauthorized"></a>

**Error:** Bad session token or header key

### Common cause
<a name="snapstart-401-unauthorized-cause"></a>

This error occurs when using the [AWS Systems Manager Parameter Store and AWS Secrets Manager extension](with-secrets-manager.md) with Lambda SnapStart.

### Resolution
<a name="snapstart-401-unauthorized-resolution"></a>

The AWS Systems Manager Parameter Store and AWS Secrets Manager extension isn't compatible with SnapStart. The extension generates credentials for communicating with AWS Secrets Manager during function initialization, which causes expired credential errors when used with SnapStart.

## UnknownHostException (Java)
<a name="snapstart-dns-caching"></a>

**Error:** Unable to execute HTTP request: Certificate for `abc.us-east-1.amazonaws.com` doesn't match any of the subject alternative names.

### Common cause
<a name="snapstart-dns-caching-cause"></a>

Lambda functions already cache DNS responses. If you use another DNS cache with SnapStart, then you might experience connection timeouts when the function resumes from a snapshot.

### Resolution
<a name="snapstart-dns-caching-resolution"></a>

To prevent `UnknownHostException` failures in the Java 11 runtime, we recommend setting `networkaddress.cache.negative.ttl` to 0. In Java 17 and later runtimes, this step isn't necessary. You can set this property for a Lambda function with the `AWS_LAMBDA_JAVA_NETWORKADDRESS_CACHE_NEGATIVE_TTL=0` environment variable.

## Snapshot creation failures
<a name="snapstart-creation-failure"></a>

**Error:** AWS Lambda could not invoke your SnapStart function. If this error persists, check your function's CloudWatch logs for initialization errors.

### Resolution
<a name="snapstart-creation-failure-resolution"></a>

Review your function's Amazon CloudWatch logs for before-checkpoint [runtime hook](snapstart-runtime-hooks.md) timeouts. You can also try publishing a new function version, which can sometimes resolve the issue.

## Snapshot creation latency
<a name="snapstart-creation-latency"></a>

**Issue:** When you publish a new function version, the function stays in the `Pending` [state](snapstart-activate.md#snapstart-function-states) for a long time.

### Common cause
<a name="snapstart-creation-latency-cause"></a>

When Lambda creates a snapshot, your initialization code can run for up to 15 minutes. The time limit is 130 seconds or the [configured function timeout](configuration-timeout.md) (maximum 900 seconds), whichever is higher.

If your function is [attached to a VPC](configuration-vpc.md#configuration-vpc-attaching), Lambda might also need to create network interfaces before the function becomes `Active`. If you try to invoke the function version while the function is `Pending`, you might get a 409 `ResourceConflictException`. If the function is invoked using an Amazon API Gateway endpoint, you might get a 500 error in API Gateway.

### Resolution
<a name="snapstart-creation-latency-resolution"></a>

Wait at least 15 minutes for the function version to initialize before invoking it.