> For the complete documentation index, see [llms.txt](https://docs.abtasty.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.abtasty.com/server-side/sdks/js-sdk/js/js-flagship-aws-lambda-integration.md).

# Flagship + AWS Lambda Integration

{% hint style="info" %}
📘 Github Repository

<https://github.com/flagship-io/flagship-aws-lambda-example>
{% endhint %}

### Overview

This guide shows how to:

* Initialize the Flagship SDK in an AWS Lambda function
* Configure the SDK for optimal performance in serverless environments
* Create a visitor object with context data from API Gateway events
* Fetch feature flags assigned to this visitor
* Retrieve specific flag values for use in the application
* Send analytics data back to Flagship
* Ensure analytics are sent before the Lambda function terminates

### Prerequisites

* [Node.js](https://nodejs.org/) (v22 or later)
* [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html)
* [Docker](https://www.docker.com/products/docker-desktop/) (for local testing)
* An [AWS account](https://aws.amazon.com/)
* A [Flagship account](https://app.flagship.io/login) with API credentials

### Setup

1. Clone the example repository:

```bash
git clone https://github.com/flagship-io/flagship-aws-lambda-example.git
cd flagship-aws-lambda-example
```

2. Install dependencies:

```bash
cd hello-world
npm install
```

3. Configure your Flagship credentials in the template.yaml file:

```yaml
Environment:
  Variables:
    FLAGSHIP_ENV_ID: "your-env-id"
    FLAGSHIP_API_KEY: "your-api-key"
```

4. Build and deploy your application:

```bash
sam build
sam deploy --guided
```

### Initialize the Flagship SDK in an AWS Lambda Function

When working with AWS Lambda, it's important to initialize the Flagship SDK outside the handler function to leverage container reuse, which improves performance for subsequent invocations.

```javascript
import {
  DecisionMode,
  Flagship,
  LogLevel,
} from "@flagship.io/js-sdk";

/**
 * Access Flagship credentials from environment variables
 */
const { FLAGSHIP_ENV_ID, FLAGSHIP_API_KEY } = process.env;

/**
 * Initialize Flagship SDK with credentials and configuration.
 * IMPORTANT: We initialize outside the handler function to leverage Lambda container reuse.
 */
await Flagship.start(FLAGSHIP_ENV_ID, FLAGSHIP_API_KEY, {
  logLevel: LogLevel.DEBUG,
  // Decision mode can be BUCKETING or DECISION_API
  decisionMode: DecisionMode.BUCKETING,
  // Defer fetching campaign data until explicitly needed
  fetchNow: false,
  // Disable polling for campaigns since Lambda functions are ephemeral
  pollingInterval: 0,
  trackingManagerConfig: {
    // Setting batchIntervals to 0 prevents background timers for analytics
    batchIntervals: 0,
  },
  // Improve performance by sending multiple activate flags in a single request
  batchActivateHits: true,
});

/**
 * AWS Lambda handler function
 */
export const lambdaHandler = async (event, context) => {
  // Your Lambda function logic here
};
```

#### Configuration Options

* **decisionMode**:
  * `BUCKETING` makes decisions locally using pre-fetched campaigns (recommended for Lambda)
  * `DECISION_API` calls Flagship servers for each decision (more network overhead)
* **fetchNow**:
  * `false` defers fetching campaign data until explicitly needed, improving cold start times
* **pollingInterval**:
  * `0` disables automatic polling since Lambda functions are ephemeral
* **trackingManagerConfig.batchIntervals**:
  * `0` prevents Flagship from using background timers for analytics, which is critical because Lambda may terminate after function completion
* **batchActivateHits**:
  * `true` improves performance by sending multiple activate flags in a single request

### Create a visitor object with context from API Gateway events

The visitor object represents a user of your application. In AWS Lambda, you can extract context data from the API Gateway event:

```javascript
// From the Lambda handler function
const visitorId = event.queryStringParameters?.visitorId;

/**
 * Create a Flagship visitor with contextual data from request headers
 */
const visitor = Flagship.newVisitor({
  visitorId,
  // Set GDPR consent status for data collection
  hasConsented: true,
  context: {
    userAgent: event.headers["user-agent"] || "unknown",
    country: event.headers["cloudfront-viewer-country"] || "unknown",
    path: event.path || "unknown",
    referrer: event.headers["referer"] || "unknown",
    // You can add any additional context that's relevant for targeting
    // isPremiumUser: event.queryStringParameters?.premium === "true",
    // deviceType: detectDeviceType(event.headers["user-agent"]),
  },
});
```

You can include any information in the context object that might be useful for targeting. API Gateway events provide access to HTTP headers, query parameters, and path information. Common examples include:

* **Demographics**: location, language preferences
* **Technical**: device type, browser, operating system
* **Behavioral**: account type, subscription status
* **Custom**: any application-specific attributes

### Fetch feature flags assigned to this visitor

Once you have a visitor object, you need to fetch the feature flags assigned to them based on targeting rules:

```javascript
// Fetch all feature flags assigned to this visitor based on targeting rules
await visitor.fetchFlags();

// Continue with Lambda function logic
```

This operation evaluates all campaign rules against the visitor's context and assigns flag variations accordingly.

### Retrieve specific flag values for use in the application

After fetching flags, you can retrieve specific flag values to control your application's behavior:

```javascript
// Retrieve specific flag values with default fallbacks
const welcomeMessage = visitor
  .getFlag("welcome_message")
  .getValue("Welcome to our site!");

const isFeatureEnabled = visitor
  .getFlag("new_feature_enabled")
  .getValue(false);

// You can get different types of values:
// Numbers
const discountPercentage = visitor
  .getFlag("discount_percentage")
  .getValue(0);

// Objects
const uiConfig = visitor
  .getFlag("ui_config")
  .getValue({
    theme: "light",
    showBanner: false,
  });

// Arrays
const enabledFeatures = visitor
  .getFlag("enabled_features")
  .getValue(["basic"]);
```

Always provide a default value that matches the expected type. This ensures your application works even if the flag isn't defined or there's an issue fetching flags.

> **Note:** Calling `getValue` automatically activates the flag, meaning it will be counted in reporting.

### Send analytics data back to Flagship

To measure the impact of your feature flags, send analytics data back to Flagship:

```javascript
/**
 * Send analytics events back to Flagship for campaign reporting and optimization.
 */
visitor.sendHits([
  {
    type: HitType.PAGE_VIEW,
    documentLocation: event.requestContext?.http?.path || event.path || "unknown",
  },
  {
    type: HitType.EVENT,
    category: EventCategory.ACTION_TRACKING,
    action: "feature_view",
    label: "new_feature",
    value: isFeatureEnabled ? 1 : 0,
  },
]);
```

Analytics data is crucial for measuring the impact of your feature flags. You can track page views, events, transactions, and more to understand how different flag variations affect user behavior.

### Ensure analytics are sent before the Lambda function terminates

AWS Lambda functions can terminate immediately after completion, potentially losing unsent analytics data. To prevent this, call `Flagship.close()` before returning:

```javascript
// Ensure all analytics data is sent before the Lambda function terminates
await Flagship.close();

// Return the response
const response = {
  statusCode: 200,
  body: JSON.stringify({
    message: welcomeMessage,
    features: {
      newFeatureEnabled: isFeatureEnabled,
    },
  }),
};

return response;
```

This ensures that all pending analytics are sent before the Lambda function terminates, giving you accurate reporting data.

### Production Considerations

When deploying this integration in production, consider the following best practices:

#### Security

1. **Environment Variables**: Store sensitive information like API keys or ENV ID in environment variables or AWS Secrets Manager.

#### Cold Starts and Warm Containers

AWS Lambda has the concept of "cold starts" and "warm containers":

* **Cold start**: First invocation after deployment or when scaling up
* **Warm container**: Subsequent invocations reusing the same container

To optimize performance:

1. Initialize the Flagship SDK outside the handler function
2. Use the Bucketing decision mode to minimize network calls
3. Set `fetchNow: false` to defer campaign fetching until needed
4. Consider using Provisioned Concurrency for critical Lambda functions

### Learn More

* [AWS Lambda Documentation](/server-side/sdks/js-sdk/js/js-flagship-aws-lambda-integration.md)
* [AWS SAM Documentation](https://docs.aws.amazon.com/serverless-application-model/)
* [Flagship JavaScript SDK Reference](/server-side/sdks/js-sdk/js-reference.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.abtasty.com/server-side/sdks/js-sdk/js/js-flagship-aws-lambda-integration.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
