Skip to content
Learni
View all tutorials
Cloud & DevOps

How to Secure Your Secrets with AWS Secrets Manager in 2026

Lire en français

Introduction

AWS Secrets Manager lets you store, manage, and retrieve secrets such as API keys, database passwords, or certificates without hardcoding them. In 2026, this practice is essential for meeting security standards and compliance requirements. This tutorial walks you through integrating AWS Secrets Manager into a Node.js TypeScript application step by step. You will learn how to configure IAM permissions, retrieve secrets efficiently, and implement a high-performance caching system.

Prerequisites

  • AWS account with IAM permissions
  • Node.js 20+ and TypeScript 5.4+
  • AWS CLI configured (aws configure)
  • Basic knowledge of Express or another Node.js framework

Installing Dependencies

terminal
npm install @aws-sdk/client-secrets-manager
dotenv

We install the official AWS SDK v3 and dotenv to load local environment variables during development.

Creating the AWS Secrets Manager Client

src/secrets/client.ts
import { SecretsManagerClient } from '@aws-sdk/client-secrets-manager';

export const secretsClient = new SecretsManagerClient({
  region: process.env.AWS_REGION || 'eu-west-3',
});

This module centralizes client creation. It uses the region defined in environment variables for flexible configuration across environments.

Retrieving a Secret

src/secrets/getSecret.ts
import { GetSecretValueCommand } from '@aws-sdk/client-secrets-manager';
import { secretsClient } from './client';

export async function getSecret(secretName: string): Promise<string> {
  const command = new GetSecretValueCommand({ SecretId: secretName });
  const response = await secretsClient.send(command);
  if (response.SecretString) {
    return response.SecretString;
  }
  throw new Error('Secret non trouvé ou binaire');
}

This function retrieves the secret in plain text. It handles only text secrets; binary secrets require different handling.

Implementing In-Memory Caching

src/secrets/secretCache.ts
const cache = new Map<string, { value: string; expires: number }>();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes

export async function getCachedSecret(secretName: string): Promise<string> {
  const now = Date.now();
  const cached = cache.get(secretName);
  if (cached && cached.expires > now) {
    return cached.value;
  }
  const value = await getSecret(secretName);
  cache.set(secretName, { value, expires: now + CACHE_TTL });
  return value;
}

Caching reduces expensive API calls and avoids rate limits. A 5-minute TTL offers a good security/performance balance.

Usage in an Express Application

src/app.ts
import express from 'express';
import { getCachedSecret } from './secrets/secretCache';

const app = express();
app.get('/config', async (req, res) => {
  try {
    const dbPassword = await getCachedSecret('prod/db/password');
    res.json({ status: 'ok' });
  } catch (error) {
    res.status(500).json({ error: 'Impossible de récupérer le secret' });
  }
});
app.listen(3000);

A practical example of using the secret in a route. The secret is never exposed in logs or source code.

Best Practices

  • Always use caching with a short TTL
  • Apply the principle of least privilege to IAM policies
  • Enable automatic secret rotation
  • Never log secret values
  • Use hierarchical secret names (prod/app/db)

Common Mistakes to Avoid

  • Forgetting to handle SDK throttling errors
  • Storing secrets in persistent environment variables
  • Failing to update IAM permissions after creating a secret
  • Using GetSecretValue instead of BatchGetSecretValue for multiple secrets

Going Further

Discover our advanced cloud security and AWS training: https://learni-group.com/formations