---
title: "AWS Secrets Manager"
lang: "en"
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/post/nodejs-aws-secrets-manager
---

![Blog post image for AWS Secrets Manager - Access secrets securely in your Node.js apps. This snippet demonstrates fetching sensitive data from AWS Secrets Manager.](/_astro/hero.BIDl4oI2_1vJUbM.webp)

[Home](/)›[Codesnippets](/codesnippets)›[All Categories](/codesnippets/categories)›[Aws](/codesnippets/categories/aws)

Codesnippets

[Prev in AwsCheck S3 Bucket Existence](/codesnippets/post/bash-s3-bucket-exists)[Next in AwsAWS DynamoDB CRUD Operations in Node.js with the AWS SDK v3](/codesnippets/post/nodejs-dynamodb-crud-aws-sdk-v3)

[Aws](/codesnippets/categories/aws)[Devops](/codesnippets/categories/devops)[Typescript](/codesnippets/typescript)

# AWS Secrets Manager

[Mohammad Abu Mattar](/authors/mohammad-abu-mattar)Published: 18 Jun 202503 Mins read02 Mins listen

[Markdown for AI(opens in a new tab)](/post/nodejs-aws-secrets-manager/index.md "Open the plain-Markdown version of this page, for pasting into an AI tool")

TL;DR

Access secrets securely in your Node.js apps. This snippet demonstrates fetching sensitive data from AWS Secrets Manager.

Series

[AWS Automation](/series/aws-automation)2/4

[PreviousCheck S3 Bucket Existence](/codesnippets/post/bash-s3-bucket-exists)[NextList S3 Buckets](/codesnippets/post/python-list-s3-buckets)

All posts in this series (4)

Code Snippets4

1.  [Check S3 Bucket Existence](/codesnippets/post/bash-s3-bucket-exists)
2.  [AWS Secrets ManagerYou are here](/codesnippets/post/nodejs-aws-secrets-manager)
3.  [List S3 Buckets](/codesnippets/post/python-list-s3-buckets)
4.  [AWS EC2 Instance Management with Boto3: Start, Stop, and Query Instances](/codesnippets/post/aws-ec2-instance-management-boto3-python)

### AWS Secrets Manager

Contents

[Loading secrets in a Node.js app without exposing them](#loading-secrets-in-a-nodejs-app-without-exposing-them)[The Problem](#the-problem)[Managing sensitive values](#managing-sensitive-values)[The Solution](#the-solution)[AWS Secrets Manager overview](#aws-secrets-manager-overview)[TL;DR](#tldr)[Code snippet (TypeScript)](#code-snippet-typescript)[Why this matters](#why-this-matters)[Over to you](#over-to-you)

### [Loading secrets in a Node.js app without exposing them](#loading-secrets-in-a-nodejs-app-without-exposing-them)

If you’re still storing API keys or database credentials in `.env` files or hardcoding them into your codebase, it’s time for a better approach. Secrets should stay secret, especially in production.

## [The Problem](#the-problem)

### [Managing sensitive values](#managing-sensitive-values)

Managing sensitive values across environments can get messy fast. Hardcoded secrets are risky, and `.env` files aren’t ideal when you’re working with teams or deploying to the cloud. It’s easy to lose control over where that information ends up.

## [The Solution](#the-solution)

### [AWS Secrets Manager overview](#aws-secrets-manager-overview)

AWS Secrets Manager gives you a safe, centralized place to store secrets. You can fetch them at runtime using the AWS SDK, so you don’t need to keep secrets on disk or in code. This snippet shows how to pull them securely in a Node.js app using SDK v3.

### [TL;DR](#tldr)

-   Use AWS Secrets Manager to securely access secrets in Node.js.
-   Avoid hardcoding secrets or using local `.env` files in production.
-   This snippet helps fetch secrets using the AWS SDK v3.

### [Code snippet (TypeScript)](#code-snippet-typescript)

fetchSecret.ts

```
1import {2  SecretsManagerClient,3  GetSecretValueCommand,4  ResourceNotFoundException,5  SecretsManagerServiceException,6} from '@aws-sdk/client-secrets-manager';7import {config} from 'dotenv';8
9config();10
11interface CachedSecret {12  value: string;13  expiry: number;14}15
16const secretCache = new Map<string, CachedSecret>();17
18const DEFAULT_CACHE_TTL = 5 * 60 * 1000;19
20const defaultRegion = process.env.AWS_REGION;21
22/**23 * Custom error for when a secret is not found in AWS Secrets Manager.24 * This is thrown when the secret does not exist or cannot be accessed.25 */26class SecretNotFoundError extends Error {27  constructor(secretName: string) {28    super(`Secret "${secretName}" not found in AWS Secrets Manager.`);29    this.name = 'SecretNotFoundError';30  }31}32
33/**34 * Custom error for when a secret's value is invalid.35 * This can happen if the secret is binary, empty, or not a string.36 */37class InvalidSecretValueError extends Error {38  constructor(secretName: string) {39    super(40      `Secret "${secretName}" is binary or empty, or does not contain a string value.`,41    );42    this.name = 'InvalidSecretValueError';43  }44}45
46let secretsManagerClient: SecretsManagerClient | null = null;47
48/**49 * Initializes and returns a singleton SecretsManagerClient.50 * This prevents recreating the client on every `fetchSecret` call.51 * @param region - The AWS region to use for the client.52 * @returns An initialized SecretsManagerClient instance.53 */54function getSecretsManagerClient(region: string): SecretsManagerClient {55  if (!region) {56    throw new Error(57      'AWS_REGION is not defined. Please set it in your .env file or pass it as an argument.',58    );59  }60  if (!secretsManagerClient) {61    secretsManagerClient = new SecretsManagerClient({region});62  }63  return secretsManagerClient;64}65
66/**67 * Fetches a secret's string value from AWS Secrets Manager with optional caching.68 * @param secretName - The name or ARN of the secret.69 * @param options - Optional configuration for fetching the secret.70 * @param options.region - Overrides the default AWS region for this fetch operation.71 * @param options.cacheTTL - Time-to-live for the cached secret in milliseconds. Set to 0 to disable caching for this call.72 * @returns A promise that resolves to the secret string.73 * @throws {SecretNotFoundError} If the secret does not exist.74 * @throws {InvalidSecretValueError} If the secret's value is binary or empty.75 * @throws {Error} For other AWS SDK or network-related errors.76 */77export async function fetchSecret(78  secretName: string,79  options?: {region?: string; cacheTTL?: number},80): Promise<string> {81  const region = options?.region || defaultRegion;82  const cacheTTL =83    options?.cacheTTL !== undefined ? options.cacheTTL : DEFAULT_CACHE_TTL;84
85  if (!region) {86    throw new Error(87      "AWS_REGION is not defined. Ensure it's in your .env file or passed in options.",88    );89  }90
91  if (cacheTTL > 0) {92    const cached = secretCache.get(secretName);93    if (cached && Date.now() < cached.expiry) {94      return cached.value;95    }96  }97
98  const client = getSecretsManagerClient(region);99
100  try {101    const command = new GetSecretValueCommand({SecretId: secretName});102    const response = await client.send(command);103
104    if (response.SecretString) {105      const secretValue = response.SecretString;106      if (cacheTTL > 0) {107        secretCache.set(secretName, {108          value: secretValue,109          expiry: Date.now() + cacheTTL,110        });111      }112      return secretValue;113    } else if (response.SecretBinary) {114      throw new InvalidSecretValueError(secretName);115    } else {116      throw new InvalidSecretValueError(secretName);117    }118  } catch (error: any) {119    console.error(`[ERROR] Failed to fetch secret "${secretName}":`, error);120    if (error instanceof ResourceNotFoundException) {121      throw new SecretNotFoundError(secretName);122    } else if (error instanceof SecretsManagerServiceException) {123      throw new Error(124        `AWS Secrets Manager error for "${secretName}": ${error.message} (Code: ${error.name})`,125      );126    } else {127      throw new Error(128        `An unexpected error occurred while fetching secret "${secretName}": ${error.message}`,129      );130    }131  } finally {132    // Add any cleanup or finalization logic here.133    // For example, if you had an active connection or resource to close.134    // In this specific code, there isn't an obvious resource to clean up135    // within the fetchSecret function itself, as the client is a singleton136    // and caching is handled by a Map.137    // However, for demonstration, you could log something:138    console.log(`[INFO] Finished attempting to fetch secret "${secretName}".`);139  }140}
```

### [Why this matters](#why-this-matters)

This setup helps keep your apps more secure and your secrets off disk. It fits well into cloud-native workflows, especially when you’re using IAM roles or CI/CD pipelines.

### [Over to you](#over-to-you)

How do you handle secrets in your projects? Tried this approach before?

Was this useful?

## Tags

[#NodeJS](/codesnippets/tags/nodejs)[#TypeScript](/codesnippets/tags/typescript)[#AWS](/codesnippets/tags/aws)[#SecretsManager](/codesnippets/tags/secretsmanager)[#CloudSecurity](/codesnippets/tags/cloudsecurity)[#DevOps](/codesnippets/tags/devops)

## Share

[Facebook](https://facebook.com/sharer/sharer.php?u=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager "Share on Facebook")[Twitter](https://twitter.com/intent/tweet/?text=AWS%20Secrets%20Manager&url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager "Share on Twitter")[LinkedIn](https://www.linkedin.com/shareArticle?mini=true&url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager&title=AWS%20Secrets%20Manager&summary=Access%20secrets%20securely%20in%20your%20Node.js%20apps.%20This%20snippet%20demonstrates%20fetching%20sensitive%20data%20from%20AWS%20Secrets%20Manager.&source=https://mkabumattar.com "Share on LinkedIn")[WhatsApp](https://wa.me/?text=AWS%20Secrets%20Manager%20https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager "Share on WhatsApp")[Telegram](https://t.me/share/url?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager&text=AWS%20Secrets%20Manager "Share on Telegram")[Reddit](https://www.reddit.com/submit?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager&title=AWS%20Secrets%20Manager "Share on Reddit")[Hacker News](http://news.ycombinator.com/submitlink?u=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager&t=AWS%20Secrets%20Manager "Share on Hacker News")[Pinterest](https://pinterest.com/pin/create/button/?url=https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager&media=&description=Access%20secrets%20securely%20in%20your%20Node.js%20apps.%20This%20snippet%20demonstrates%20fetching%20sensitive%20data%20from%20AWS%20Secrets%20Manager. "Share on Pinterest")[Email](<mailto:?subject=AWS%20Secrets%20Manager&body=Check out this article: https%3A%2F%2Fmkabumattar.com%2Fcodesnippets%2Fpost%2Fnodejs-aws-secrets-manager>)

## Comments

## You might also enjoy

More posts on similar topics

[![Check S3 Bucket Existence](/_astro/hero.CWiO4GWV_1YUYTb.webp)](/codesnippets/post/bash-s3-bucket-exists)

## [Check S3 Bucket Existence](/codesnippets/post/bash-s3-bucket-exists)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Aws](/codesnippets/categories/aws)
-   [Shell scripting](/codesnippets/categories/shell-scripting)
-   [Devops](/codesnippets/categories/devops)

Quick Tip Don't let your deployment blow up because of a missing S3 bucket. This Bash script lets you check if a bucket exists before anything fails. The Problem Missing bucket failure

[#Bash](/codesnippets/tags/bash)[#AWS](/codesnippets/tags/aws)[#DevOps](/codesnippets/tags/devops)+3 tags

[read more](/codesnippets/post/bash-s3-bucket-exists)

[![List S3 Buckets](/_astro/hero.BsiJ6hry_1X9XLn.webp)](/codesnippets/post/python-list-s3-buckets)

## [List S3 Buckets](/codesnippets/post/python-list-s3-buckets)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Aws](/codesnippets/categories/aws)
-   [Python](/codesnippets/categories/python)
-   [Devops](/codesnippets/categories/devops)

Overview Multi-profile S3 management Ever juggled multiple AWS accounts and needed a quick S3 bucket inventory across all of them? This Python script handles it. Use case Perfect for or

[#Python](/codesnippets/tags/python)[#Boto3](/codesnippets/tags/boto3)[#AWS](/codesnippets/tags/aws)+5 tags

[read more](/codesnippets/post/python-list-s3-buckets)

[![AWS EC2 Instance Management with Boto3: Start, Stop, and Query Instances](/_astro/hero.PnHlvJay_ZkFqWG.webp)](/codesnippets/post/aws-ec2-instance-management-boto3-python)

## [AWS EC2 Instance Management with Boto3: Start, Stop, and Query Instances](/codesnippets/post/aws-ec2-instance-management-boto3-python)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Cloud](/codesnippets/categories/cloud)
-   [Aws](/codesnippets/categories/aws)
-   [Devops](/codesnippets/categories/devops)
-   [Automation](/codesnippets/categories/automation)

If you've ever spent 20 minutes clicking through the AWS Console just to stop a handful of dev instances, you already know the pain. It's tedious, it doesn't scale, and one wrong click can ruin your a

[#AWS](/codesnippets/tags/aws)[#EC2](/codesnippets/tags/ec2)[#Boto3](/codesnippets/tags/boto3)+6 tags

[read more](/codesnippets/post/aws-ec2-instance-management-boto3-python)

[![AWS DynamoDB CRUD Operations in Node.js with the AWS SDK v3](/_astro/hero.CceR-orf_Z2scRI0.webp)](/codesnippets/post/nodejs-dynamodb-crud-aws-sdk-v3)

## [AWS DynamoDB CRUD Operations in Node.js with the AWS SDK v3](/codesnippets/post/nodejs-dynamodb-crud-aws-sdk-v3)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Nodejs](/codesnippets/categories/nodejs)
-   [Aws](/codesnippets/categories/aws)
-   [Database](/codesnippets/categories/database)

Quick Tip Wrap the low-level DynamoDB client in a DynamoDBDocumentClient so you pass plain JavaScript objects in and get plain objects back, then guard your writes with ConditionExpression an

[#DynamoDB](/codesnippets/tags/dynamodb)[#Node.js](/codesnippets/tags/nodejs)[#AWS SDK v3](/codesnippets/tags/aws-sdk-v3)+3 tags

[read more](/codesnippets/post/nodejs-dynamodb-crud-aws-sdk-v3)

[![Bash Retry Function: Automatically Retry Failing Commands with Exponential Backoff](/_astro/hero.Dap62rVN_Z1q0nar.webp)](/codesnippets/post/bash-retry-function-exponential-backoff)

## [Bash Retry Function: Automatically Retry Failing Commands with Exponential Backoff](/codesnippets/post/bash-retry-function-exponential-backoff)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Devops](/codesnippets/categories/devops)
-   [Shell scripting](/codesnippets/categories/shell-scripting)
-   [Automation](/codesnippets/categories/automation)

Quick Tip Wrap any flaky command in one reusable retry function and stop re-running red pipelines by hand. The Problem The Problem Some commands fail for reasons that have nothing to

[#Bash](/codesnippets/tags/bash)[#Retry](/codesnippets/tags/retry)[#Exponential Backoff](/codesnippets/tags/exponential-backoff)+3 tags

[read more](/codesnippets/post/bash-retry-function-exponential-backoff)

[![Essential Bash Variables for Every Script](/_astro/hero.B4bDowyY_YQpD7.webp)](/codesnippets/post/essential-bash-variables)

## [Essential Bash Variables for Every Script](/codesnippets/post/essential-bash-variables)

-   [Mohammad Abu Mattar](/authors/mohammad-abu-mattar)
-   [Shell scripting](/codesnippets/categories/shell-scripting)
-   [Devops](/codesnippets/categories/devops)

Overview Quick Tip You know what's worse than writing scripts? Writing scripts that break every time you move them to a different machine. Built-in Bash variables fix that. The problem wi

[#Bash](/codesnippets/tags/bash)[#Shell Scripting](/codesnippets/tags/shell-scripting)[#Linux](/codesnippets/tags/linux)+4 tags

[read more](/codesnippets/post/essential-bash-variables)

6 related posts
