npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@elsikora/nestjs-aws-parameter-store-config

v2.0.2

Published

NestJS application configuration with AWS Parameter Store

Readme

💡 Highlights

  • 🏗️ Canonical SSM Contract — Enforces a deterministic ///// model, eliminating ad-hoc parameter naming chaos across teams
  • ⚡ Single Recursive Load — Fetches all parameters under // at startup into an in-memory cache, serving lookups instantly with zero runtime SSM calls
  • 🛡️ Fail-Fast Validation — Catches missing segments, empty strings, whitespace, and illegal '/' characters at boot time with explicit error messages
  • 🔌 Broad NestJS Compatibility — Supports NestJS v8 through v11 with both register() and registerAsync() patterns, including factory, class, and existing provider injection

📚 Table of Contents

📖 Description

Managing application configuration across multiple environments, namespaces, and deployment targets is one of the most error-prone aspects of cloud-native development. NestJS AWS Parameter Store Config eliminates that complexity by enforcing a single, canonical SSM path contract:

/<application>/<environment>/<namespace>/<instanceName>/<path...>

This module provides a first-class NestJS dynamic module that loads all parameters at startup into an in-memory cache, then exposes a type-safe, validated lookup API that resolves paths deterministically.

Real-World Use Cases

  • Microservices on ECS/EKS: Each service registers with its own namespace and instanceName, while sharing infrastructure parameters (database hosts, secret IDs) across namespaces.
  • Multi-Environment Deployments: Seamlessly switch between local, development, staging, and production without changing a single line of application code.
  • Shared Infrastructure Metadata: A single recursive load from /<app>/<env> caches everything — RDS connection strings, Secrets Manager references, CloudWatch config — accessible via simple path lookups.
  • Monorepo / Multi-Service Architectures: Different services can override namespace and instanceName per-call, accessing any parameter in the hierarchy without re-registering the module.

With built-in enums for 90+ namespace tokens (AWS, GCP, Azure, databases, message brokers, and more), strict validation that fails fast on misconfigured paths, and support for both synchronous and async module registration, this library turns AWS Parameter Store into a structured, predictable configuration backbone for your NestJS applications.

🛠️ Tech Stack

| Category | Technologies | |----------|-------------| | Language | TypeScript | | Runtime | Node.js | | Framework | NestJS | | Cloud | AWS Systems Manager (SSM) | | Build Tool | Rollup, TypeScript Compiler | | Linting | ESLint, Prettier | | CI/CD | GitHub Actions, Semantic Release | | Package Manager | npm | | Code Quality | Husky, Commitlint, Lint-Staged |

🚀 Features

  • Canonical Path Contract — All parameter lookups resolve through a strict /<application>/<environment>/<namespace>/<instanceName>/<path> model, ensuring consistency across all services and environments
  • Recursive Parameter Loading — Loads all parameters under /<application>/<environment> at startup using paginated SSM API calls, building an in-memory cache for instant lookups
  • Sync & Async Module Registration — Supports register() for static config and registerAsync() with useFactory, useClass, and useExisting patterns for dynamic configuration
  • Per-Call Overrides — Override namespace, instanceName, application, or environment on any individual get() call while keeping module-level defaults
  • 90+ Built-In Namespace Tokens — Curated ENamespace enum covering AWS, GCP, Azure services, databases, message brokers, observability tools, and more
  • Lifecycle Environment EnumEEnvironment provides LOCAL, DEVELOPMENT, STAGING, PRODUCTION, and TEST tokens out of the box
  • Strict Input Validation — Fails fast with descriptive errors for missing segments, empty strings, whitespace-only values, and segments containing /
  • Dual Module Output — Ships both ESM and CommonJS builds with full TypeScript declarations and source maps
  • Secure Parameter Decryption — Optional shouldDecryptParameters flag enables transparent decryption of SecureString parameters
  • Verbose Logging Mode — Optional isVerbose flag enables detailed NestJS Logger output during parameter loading for debugging
  • Global Module — Registered as a @Global() module, making ParameterStoreConfigService injectable anywhere without re-importing
  • Zero Runtime Dependencies — Peer dependencies only — @aws-sdk/client-ssm and @nestjs/common are provided by your application

🏗 Architecture

System Architecture

flowchart TD
    appModule[AppModule] -->|imports| configModule[ParameterStoreConfigModule]
    configModule -->|provides| propertiesProvider[PropertiesProvider]
    configModule -->|provides| ssmProvider[SSMClientProvider]
    configModule -->|provides| parametersProvider[ParametersProvider]
    configModule -->|provides| parameterStoreService[ParameterStoreService]
    configModule -->|exports| configService[ParameterStoreConfigService]
    ssmProvider -->|creates| ssmClient[SSMClient]
    parameterStoreService -->|uses| ssmClient
    parametersProvider -->|calls| parameterStoreService
    configService -->|reads| propertiesProvider
    configService -->|reads| parametersProvider
    anyService[Any Injectable Service] -->|injects| configService

Data Flow

sequenceDiagram
    participant App as NestJS App
    participant Module as ConfigModule
    participant SSMProvider as SSMClientProvider
    participant ParamProvider as ParametersProvider
    participant PSService as ParameterStoreService
    participant AWS as AWS SSM API
    participant Service as Your Service
    participant ConfigSvc as ConfigService

    App->>Module: register() / registerAsync()
    Module->>SSMProvider: Create SSMClient with config
    SSMProvider-->>Module: SSMClient instance
    Module->>ParamProvider: Initialize parameter loading
    ParamProvider->>PSService: getParametersByPath(/app/env)
    loop Paginated Loading
        PSService->>AWS: GetParametersByPathCommand
        AWS-->>PSService: Parameters + NextToken
    end
    PSService-->>ParamProvider: All Parameter[] cached
    ParamProvider-->>Module: In-memory parameter cache ready
    Service->>ConfigSvc: get({ path, namespace?, ... })
    ConfigSvc->>ConfigSvc: buildLookupPath() + validate
    ConfigSvc->>ConfigSvc: Find in cached parameters
    ConfigSvc-->>Service: string value or null

📁 Project Structure

NestJS-AWS-Parameter-Store-Config/
├── .github/
│   ├── workflows/
│   │   ├── mirror-to-codecommit.yml
│   │   ├── qodana-quality-scan.yml
│   │   ├── release.yml
│   │   └── snyk-security-scan.yml
│   └── dependabot.yml
├── src/
│   ├── modules/
│   │   ├── aws/
│   │   └── config/
│   ├── shared/
│   │   ├── constant/
│   │   ├── enum/
│   │   ├── interface/
│   │   └── provider/
│   └── index.ts
├── CHANGELOG.md
├── commitlint.config.js
├── eslint.config.js
├── LICENSE
├── lint-staged.config.js
├── nest-cli.json
├── package-lock.json
├── package.json
├── prettier.config.js
├── README.md
├── release.config.js
├── rollup.config.js
├── tsconfig.build.json
└── tsconfig.json

📋 Prerequisites

  • Node.js >= 16.0.0
  • npm >= 8.0.0
  • NestJS >= 8.0.0 (supports v8, v9, v10, v11)
  • @aws-sdk/client-ssm >= 3.535.0
  • AWS credentials configured (IAM role, environment variables, or AWS CLI profile)
  • AWS SSM parameters created following the canonical path convention

🛠 Installation

# Install the package and its required peer dependencies
npm install @elsikora/nestjs-aws-parameter-store-config @aws-sdk/client-ssm @nestjs/common

# Or with Yarn
yarn add @elsikora/nestjs-aws-parameter-store-config @aws-sdk/client-ssm @nestjs/common

# Or with pnpm
pnpm add @elsikora/nestjs-aws-parameter-store-config @aws-sdk/client-ssm @nestjs/common


### Building from Source


# Clone the repository
git clone https://github.com/ElsiKora/NestJS-AWS-Parameter-Store-Config.git
cd NestJS-AWS-Parameter-Store-Config

# Install dependencies
npm install

# Build ESM and CJS outputs
npm run build

# Run linting
npm run lint:all

# Type check
npm run lint:types

💡 Usage

Quick Start

1. Register the Module

Add ParameterStoreConfigModule to your root AppModule with your canonical defaults:

import { Module } from "@nestjs/common";
import {
  EEnvironment,
  ENamespace,
  ParameterStoreConfigModule,
} from "@elsikora/nestjs-aws-parameter-store-config";

@Module({
  imports: [
    ParameterStoreConfigModule.register({
      application: "gameport",
      environment: EEnvironment.STAGING,
      namespace: ENamespace.AWS_ECS_FARGATE,
      instanceName: "reaper-api",
      shouldDecryptParameters: true,
      config: {
        region: "eu-north-1",
      },
    }),
  ],
})
export class AppModule {}

2. Async Registration with ConfigService

For dynamic configuration that depends on environment variables or other providers:

import { Module } from "@nestjs/common";
import { ConfigModule, ConfigService } from "@nestjs/config";
import {
  EEnvironment,
  ENamespace,
  ParameterStoreConfigModule,
} from "@elsikora/nestjs-aws-parameter-store-config";

@Module({
  imports: [
    ConfigModule.forRoot(),
    ParameterStoreConfigModule.registerAsync({
      imports: [ConfigModule],
      inject: [ConfigService],
      useFactory: (configService: ConfigService) => ({
        application: configService.getOrThrow("APP_NAME"),
        environment: configService.getOrThrow("NODE_ENV"),
        namespace: ENamespace.AWS_ECS_FARGATE,
        instanceName: configService.getOrThrow("SERVICE_NAME"),
        shouldDecryptParameters: true,
        shouldUseRecursiveLoading: true,
        isVerbose: configService.get("VERBOSE") === "true",
        config: {
          region: configService.getOrThrow("AWS_REGION"),
        },
      }),
    }),
  ],
})
export class AppModule {}

3. Inject and Use the Service

Since the module is @Global(), you can inject ParameterStoreConfigService in any provider:

import { Injectable } from "@nestjs/common";
import {
  ENamespace,
  ParameterStoreConfigService,
} from "@elsikora/nestjs-aws-parameter-store-config";

@Injectable()
export class DatabaseService {
  constructor(
    private readonly config: ParameterStoreConfigService,
  ) {}

  getDatabaseHost(): string {
    // Resolves: /gameport/staging/aws-rds/aurora-postgres/host
    return this.config.get({
      namespace: ENamespace.AWS_RDS,
      instanceName: "aurora-postgres",
      path: ["host"],
    }) ?? "localhost";
  }

  getDatabasePort(): number {
    // Resolves: /gameport/staging/aws-rds/aurora-postgres/port
    const port = this.config.get({
      namespace: ENamespace.AWS_RDS,
      instanceName: "aurora-postgres",
      path: ["port"],
    });
    return port ? parseInt(port, 10) : 5432;
  }
}

4. Cross-Namespace Lookups

Access parameters from different namespaces without re-registering:

@Injectable()
export class AppConfigService {
  constructor(
    private readonly config: ParameterStoreConfigService,
  ) {}

  // Uses module defaults: /gameport/staging/aws-ecs-fargate/reaper-api/api/version
  getApiVersion(): string | null {
    return this.config.get({ path: ["api", "version"] });
  }

  // Override namespace: /gameport/staging/aws-secrets-manager/database/secret-id
  getDatabaseSecretId(): string | null {
    return this.config.get({
      namespace: ENamespace.AWS_SECRETS_MANAGER,
      instanceName: "database",
      path: ["secret-id"],
    });
  }

  // Override everything: /other-app/production/aws-lambda/processor/timeout
  getExternalConfig(): string | null {
    return this.config.get({
      application: "other-app",
      environment: "production",
      namespace: ENamespace.AWS_LAMBDA,
      instanceName: "processor",
      path: ["timeout"],
    });
  }
}

5. Custom Namespace Strings

Not limited to the built-in enums — pass any string:

this.config.get({
  namespace: "custom-service",
  instanceName: "my-instance",
  path: ["some", "deep", "config"],
});
// Resolves: /gameport/staging/custom-service/my-instance/some/deep/config

Configuration Options Reference

| Option | Type | Required | Default | Description | |--------|------|----------|---------|-------------| | application | string | ✅ | — | Product/system name (first path segment) | | environment | EEnvironment \| string | ✅ | — | Lifecycle environment token | | namespace | ENamespace \| string | ✅ | — | Default owner/runtime/resource token | | instanceName | string | ✅ | — | Default deployable unit or resource instance | | config | SSMClientConfig | ❌ | {} | AWS SSM client configuration | | shouldDecryptParameters | boolean | ❌ | false | Decrypt SecureString parameters | | shouldUseRecursiveLoading | boolean | ❌ | true | Recursively load all nested parameters | | isVerbose | boolean | ❌ | false | Enable verbose logging during parameter loading |

🛣 Roadmap

| Task / Feature | Status | |---|---| | Canonical SSM path contract (/<app>/<env>/<ns>/<instance>/<path>) | ✅ Done | | Sync and async module registration | ✅ Done | | Paginated recursive parameter loading | ✅ Done | | Per-call namespace and instance overrides | ✅ Done | | Strict input validation with fail-fast errors | ✅ Done | | Dual ESM/CJS module output with source maps | ✅ Done | | Built-in ENamespace enum (90+ tokens) | ✅ Done | | Verbose logging mode | ✅ Done | | Automated semantic releases with backmerge | ✅ Done | | TTL-based parameter cache refresh | 🚧 In Progress | | Parameter change event subscriptions | 🚧 In Progress | | Batch getMany() API for multi-path lookups | 🚧 In Progress | | Optional Zod/class-validator schema validation on retrieved values | 🚧 In Progress | | Unit and integration test suite | 🚧 In Progress |

❓ FAQ

❓ Frequently Asked Questions

Q: Does this module make SSM API calls on every get() invocation?

A: No. All parameters are loaded once at module initialization (startup) into an in-memory cache. The get() method performs a simple array lookup against the cached parameters — there are zero runtime SSM API calls.


Q: How does the module handle large numbers of parameters?

A: The ParameterStoreService automatically handles SSM API pagination. It continues fetching pages using NextToken until all parameters under /<application>/<environment> are loaded.


Q: Can I use custom strings instead of the built-in enums?

A: Yes! Both environment and namespace accept string types in addition to EEnvironment and ENamespace enums. This allows you to use custom tokens like "my-custom-namespace" when the built-in options don't fit.


Q: Which NestJS versions are supported?

A: The module supports NestJS v8, v9, v10, and v11 through a flexible peer dependency range (^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0).


Q: Do I need to import the module in every feature module?

A: No. ParameterStoreConfigModule is decorated with @Global(), so once registered in your root AppModule, the ParameterStoreConfigService is injectable in any provider across your application.


Q: What happens if a required segment (application, environment, etc.) is missing?

A: The module throws a descriptive error immediately at startup or at lookup time. It validates that no segment is undefined, null, empty, whitespace-only, or contains / characters.


Q: How do I decrypt SecureString parameters?

A: Set shouldDecryptParameters: true in your module registration options. This passes WithDecryption: true to the SSM GetParametersByPathCommand.


Q: Can I access parameters from a different application or environment?

A: Yes, but with a caveat. The get() method accepts per-call overrides for application and environment, but the in-memory cache only contains parameters loaded from the module's configured /<application>/<environment> prefix. To access parameters from a different prefix, you'd need to register a second module instance or ensure those parameters exist under the loaded prefix.

🔒 License

This project is licensed under MIT.

🙏 Acknowledgments

🙏 Acknowledgments


Built with ❤️ for the NestJS community