From 851b3db39ab25b8deadc38c07afb6947039c2e7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivar=20Conradi=20=C3=98sthus?= Date: Mon, 19 Feb 2024 17:29:10 +0100 Subject: [PATCH] docs: tutorial on node-sdk with aws lambda (#6258) This is a docs tutorial on how to use the Unleash Node SDK in an AWS Lambda. (Peer reviewed outside of Git.) --- ...mplementing-feature-flags-in-aws-lambda.md | 142 ++++++++++++++++++ website/sidebars.js | 6 + website/static/img/lambda-architecture.png | Bin 0 -> 33739 bytes 3 files changed, 148 insertions(+) create mode 100644 website/docs/feature-flag-tutorials/serverless/implementing-feature-flags-in-aws-lambda.md create mode 100644 website/static/img/lambda-architecture.png diff --git a/website/docs/feature-flag-tutorials/serverless/implementing-feature-flags-in-aws-lambda.md b/website/docs/feature-flag-tutorials/serverless/implementing-feature-flags-in-aws-lambda.md new file mode 100644 index 0000000000..085d7faf7e --- /dev/null +++ b/website/docs/feature-flag-tutorials/serverless/implementing-feature-flags-in-aws-lambda.md @@ -0,0 +1,142 @@ +--- +title: How to implement feature flags in a serverless environment using AWS Lambda +slug: /feature-flag-tutorials/serverless/lambda +--- + +For developers new to feature flags in serverless environments, this guide will walk you through practical examples using the [Unleash Node.js SDK](https://github.com/Unleash/unleash-client-node) in [AWS Lambda](https://aws.amazon.com/lambda/). These concepts can be easily adapted to other serverless solutions like [Google Cloud Functions](https://cloud.google.com/functions). Having feature flagging capabilities available inside of your serverless functions allows you to validate new parts of your serverless functions and stay in control of the feature exposure. + + +![AWS Lambda connecting to Unleash](/img/lambda-architecture.png) + + +## Step 1: Initialize the SDK. + +In order to use any Unleash SDK, it needs to be initialized. This is when the SDK is configured with the necessary details to connect to the Unleash API. As part of initialization, the SDK downloads the most recent configuration from Unleash. The SDK also synchronizes with the Unleash API in the background, ensuring updates propagate to the Lambda functions. + +It's essential to understand that the Unleash SDK should be initialized only once during the lifespan of a serverless function. This approach is critical to avoid the overhead of connecting to the external Unleash API with every invocation of an AWS Lambda. AWS Lambda is designed to reuse the same instance for multiple invocations, enabling the expensive initialization process to occur only during the Lambda's "cold start." Subsequent "warm" invocations can then leverage the SDK, which has been pre-initialized, with all feature flag configurations cached in memory. This ensures efficient operation by minimizing initialization overhead and enhancing performance. + +You will also have to provide a [Unleash Server side API](https://docs.getunleash.io/how-to/how-to-create-api-tokens) Token as an environment variable for the AWS Lambda in order for the SDK to be able to connect to the Unleash API. + + +```javascript +import { startUnleash, InMemStorageProvider, destroyWithFlush } from 'unleash-client'; +let unleash; + +async function init() { + if (!unleash) { + unleash = await startUnleash({ + url: 'https://sandbox.getunleash.io/enterprise/api/', + appName: 'lambda-example-app', + customHeaders: { + authorization: process.env.API_TOKEN, + }, + storageProvider: new InMemStorageProvider(), + }); + unleash.on('initialized', () => console.log('[runtime] Unleash initialized')); + } +} + +export const handler = async (event, context) => { + // Only the first invocation will trigger SDK initialization. + await init(); + return { + statusCode: 200, + body: {message: ``}, + }; +}; +``` + +## Step 2: Add graceful shutdown of the SDKs +It’s important to handle the case of a Lambda shutting down in a graceful manner in order to preserve usage metrics. Fortunately, AWS Lambda receives a signal when AWS decides that the Lambda instance is not needed anymore. We can use this signal to make sure we send any outstanding cached usage metrics to Unleash API. + +The code below shows how we can add the listener in the “global” part of our function in order to destroy the Unleash SDK gracefully and make sure we flush any outstanding metrics back to the Unleash API. + + +```javascript +let unleash; + +process.on('SIGTERM', async () => { + console.info('[runtime] SIGTERM received'); + + if(unleash) { + await destroyWithFlush(); + unleash = undefined; + } + + process.exit(0) +}); + +``` + +### Step 3: Use the Unleash SDK for feature flagging + +Now that we have Unleash SDK properly initialized and we have a graceful shutdown hook, it's time to start taking advantage of feature flags in our serverless function. + +Luckily this is relatively straightforward, and we can just use the SDK as we would in any Node.js application. In the example below, we read the value of the “**simpleFlag**” and return the status as part of the JSON response from the function. + +```javascript +import { startUnleash, InMemStorageProvider, destroyWithFlush } from 'unleash-client'; + +let unleash; + +async function init() { + if (!unleash) { + console.log('[runtime] Starting unleash'); + unleash = await startUnleash({ + url: 'https://sandbox.getunleash.io/enterprise/api/', + appName: 'lambda-example-app', + customHeaders: { + authorization: process.env.API_TOKEN, + }, + storageProvider: new InMemStorageProvider(), + }); + unleash.on('initialized', () => console.log('[runtime] Unleash initialized')); + } +} + +process.on('SIGTERM', async () => { + console.info('[runtime] SIGTERM received'); + + if(unleash) { + await destroyWithFlush(); + unleash = undefined; + } + + process.exit(0) +}); + +export const handler = async (event, context) => { + // Only the first invocation will trigger SDK initialization. + await init(); + + const isEnabled = unleash.isEnabled('simpleFlag') + + return { + statusCode: 200, + body: {message: `Feature flag 'simpleFlag' is ${isEnabled ? 'enabled' : 'disabled'}`}, + }; +}; +``` + +In our Lambda setup we have enabled a [public function URL](https://docs.aws.amazon.com/lambda/latest/dg/lambda-urls.html), which allows us to trigger the function easily via the public URL of the function. + +Example: + +```bash +curl https://z5w5lkzlsozutfhaixbjsj27cm0dhnfh.lambda-url.eu-north-1.on.aws + +{"message":"Feature flag 'simpleFlag' is enabled"} +``` + +## Conclusion + +Mastering feature flags in serverless? This guide demonstrated the surprisingly simple use of Unleash SDK. Remember, avoid initializing the SDK multiple times within your serverless function for smooth operation. + +If you plan to have thousands of RPS towards your lambda you should consider [Unleash Edge](https://docs.getunleash.io/understanding-unleash/proxy-hosting), a component built to scale your usage of Unleash. + + +:::note Lambda latency + +If you care about latency and particularly faster cold starts you should take a look at [Low Latency Runtime](https://github.com/awslabs/llrt) (LTR) an experimental, lightweight JavaScript runtime designed to address the growing demand for fast and efficient Serverless applications. The team behind Unleash is super excited about this initiative. + +::: \ No newline at end of file diff --git a/website/sidebars.js b/website/sidebars.js index d66b6c36c3..68276a7658 100644 --- a/website/sidebars.js +++ b/website/sidebars.js @@ -130,6 +130,11 @@ module.exports = { }, ], }, + { + type: 'doc', + label: 'Serverless', + id: 'feature-flag-tutorials/serverless/implementing-feature-flags-in-aws-lambda', + }, { type: 'doc', label: 'Flutter', @@ -140,6 +145,7 @@ module.exports = { label: 'Next.js', id: 'feature-flag-tutorials/nextjs/implementing-feature-flags', }, + ], }, { diff --git a/website/static/img/lambda-architecture.png b/website/static/img/lambda-architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..d6d9e87e7311d318e43b98249361a3c96a58a728 GIT binary patch literal 33739 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