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

中文文档
3.0.0发布于 2026/11/03MITTypeScriptES Module零依赖近 30 天下载 6675

NestJS application configuration with AWS Parameter Store

原始使用文档
文档目录27 节
  1. 💡 Highlights
  2. 📚 Table of Contents
  3. 📖 Description
  4. Real-World Use Cases
  5. 🛠️ Tech Stack
  6. 🚀 Features
  7. 🏗 Architecture
  8. System Architecture
  9. Data Flow
  10. 📁 Project Structure
  11. 📋 Prerequisites
  12. 🛠 Installation
  13. 💡 Usage
  14. Quick Start
  15. 1. Register the Module
  16. 2. Async Registration with ConfigService
  17. 3. Inject and Use the Service
  18. 4. Cross-Namespace Lookups
  19. 5. Custom Namespace Strings
  20. Configuration Options Reference
  21. 🔄 Migration Notes
  22. Migrating to 3.0
  23. 🛣 Roadmap
  24. ❓ FAQ
  25. ❓ Frequently Asked Questions
  26. 🔒 License
  27. 🙏 Acknowledgments

project-logo

🔐 NestJS AWS Parameter Store Config

Seamless NestJS integration with AWS Systems Manager Parameter Store — one canonical SSM contract to rule all your configuration.

ElsiKora TypeScript Node.js NestJS AWS npm Rollup ESLint Prettier GitHub Actions Git

💡 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
  • 🔌 NestJS 12 and ES Modules — Built for NestJS 12 as an ES module package that CommonJS applications load through Node.js require(esm), with 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

CategoryTechnologies
LanguageTypeScript
RuntimeNode.js
FrameworkNestJS
CloudAWS Systems Manager (SSM)
Build ToolRollup, TypeScript Compiler
LintingESLint, Prettier
CI/CDGitHub Actions, Semantic Release
Package Managernpm
Code QualityHusky, 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 Enum — EEnvironment 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 /
  • ✨ ES Module Package — Ships one ES module build with source maps and TypeScript declarations whose relative imports carry .js extensions, so bundler, nodenext and CommonJS node10 consumers all typecheck
  • ✨ 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

Click to expand
NestJS-AWS-Parameter-Store-Config/
├── .github/
│   ├── workflows/
│   │   ├── mirror-to-codecommit.yml
│   │   ├── qodana-quality-scan.yml
│   │   ├── release.yml
│   │   ├── snyk-security-scan.yml
│   │   └── test.yml
│   └── dependabot.yml
├── scripts/
│   ├── test/
│   │   └── consumer-smoke.mjs
│   └── check-declaration-imports.cjs
├── src/
│   ├── modules/
│   │   ├── aws/
│   │   └── config/
│   ├── shared/
│   │   ├── constant/
│   │   ├── enum/
│   │   ├── interface/
│   │   └── provider/
│   └── index.ts
├── test/
│   ├── consumer/
│   └── unit/
├── CHANGELOG.md
├── commitlint.config.js
├── eslint.config.js
├── LICENSE
├── lint-staged.config.js
├── nest-cli.json
├── package.json
├── prettier.config.js
├── README.md
├── release.config.js
├── rollup.config.js
├── tsconfig.build.json
├── tsconfig.json
└── vitest.unit.config.js

📋 Prerequisites

  • Node.js ^22.13.0 || >=24.11.0
  • @nestjs/common >=12.3.2 <13
  • @aws-sdk/client-ssm >=3.535.0 <4
  • 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 the ES module output and check its imports
npm run build

# Run linting
npm run lint:all

# Type check
npm run lint:types

# Run unit tests
npm run test:unit

# Pack the build and run it in ESM (bundler, nodenext) and CommonJS (node10, default resolution) consumer apps
npm run test:consumer

💡 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

OptionTypeRequiredDefaultDescription
applicationstring✅—Product/system name (first path segment)
environmentEEnvironment | string✅—Lifecycle environment token
namespaceENamespace | string✅—Default owner/runtime/resource token
instanceNamestring✅—Default deployable unit or resource instance
configSSMClientConfig❌{}AWS SSM client configuration
shouldDecryptParametersboolean❌falseDecrypt SecureString parameters
shouldUseRecursiveLoadingboolean❌trueRecursively load all nested parameters
isVerboseboolean❌falseEnable verbose logging during parameter loading

🔄 Migration Notes

Migrating to 3.0

3.0.0 moves the package to NestJS 12 and ships it as ES modules only. The configuration API, the canonical path contract and the exported names do not change.

Requirement2.x3.0
Node.js16 and later^22.13.0 || >=24.11.0
@nestjs/common^8 || ^9 || ^10 || ^11>=12.3.2 <13
Module formatESM and CommonJSESM only
  1. Upgrade Node.js and NestJS first, following the NestJS migration guide. Applications on NestJS 11 or older, or on Node.js 20, stay on 2.x.
  2. Install peers with explicit ranges, for example npm install @nestjs/common@^12 @aws-sdk/client-ssm@^3, and check the tree with npm ls.
  3. Import only from the package root. The 2.x exports map already had only ., so Node.js never resolved deep imports. 3.0 also removes dist/esm, dist/cjs and the require condition, so TypeScript with node10 resolution, which ignores exports, no longer finds types for deep paths such as @elsikora/nestjs-aws-parameter-store-config/dist/cjs/... either.

ES module applications import the package as before, with moduleResolution set to bundler, node16 or nodenext. The declarations now carry .js extensions on every relative import, so nodenext consumers get the types.

CommonJS applications keep require("@elsikora/nestjs-aws-parameter-store-config"). Node.js loads the ES module through require(esm), which works without a flag on every supported Node.js release. TypeScript with module: commonjs finds the types either way: with moduleResolution: node10 through the top-level types field (TypeScript 6 then needs "ignoreDeprecations": "6.0"), and without moduleResolution, which TypeScript 6 resolves as bundler, through exports.

Importing the package has no side effects: it loads no .env file and writes nothing to the console. Logging happens only while parameters load and only with isVerbose: true. CI checks this on the packed tarball.

🛣 Roadmap

Click to expand
Task / FeatureStatus
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
ES module output with extension-qualified declarations✅ Done
NestJS 12 support✅ 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 test suite and packed-tarball consumer smoke tests✅ Done

❓ FAQ

Click to expand

❓ 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: 3.x supports NestJS 12 (@nestjs/common >=12.3.2 <13). For NestJS 8 to 11, use 2.x.


Q: Can I use the package from a CommonJS application?

A: Yes. The package is an ES module, and Node.js ^22.13.0 || >=24.11.0 loads it from require() through require(esm). TypeScript finds the types through the top-level types field with node10 resolution and through exports with node16, nodenext or bundler, which is also what TypeScript 6 uses for module: commonjs without moduleResolution. See Migration Notes.


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

  • NestJS — The progressive Node.js framework that makes building server-side applications a joy
  • AWS SDK for JavaScript v3 — The modular AWS SDK powering the SSM client
  • AWS Systems Manager Parameter Store — The secure, hierarchical configuration storage service
  • Semantic Release — Fully automated version management and package publishing
  • Rollup — The module bundler producing the ES module output
  • ElsiKora — The team behind this module and the broader tooling ecosystem

Built with ❤️ for the NestJS community


Back to Top

版本与发布记录

@elsikora/nestjs-aws-parameter-store-config 共发布 32 个版本,首次发布于 2024/03/17;过去 12 个月发布了 8 个版本。

版本发布日期距今
3.0.0latest2026/11/0310 天前
3.0.0-dev.1beta2026/11/0112 天前
2.0.22026/03/138 个月前
2.0.2-dev.12026/03/138 个月前
2.0.12026/03/128 个月前
2.0.1-dev.12026/03/128 个月前

关于 @elsikora/nestjs-aws-parameter-store-config 的常见问题

@elsikora/nestjs-aws-parameter-store-config 是什么?

NestJS application configuration with AWS Parameter Store

如何安装 @elsikora/nestjs-aws-parameter-store-config?

在项目目录运行 npm install @elsikora/nestjs-aws-parameter-store-config,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@nestjs/common(>=12.3.2 <13)、@aws-sdk/client-ssm(>=3.535.0 <4)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@elsikora/nestjs-aws-parameter-store-config 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@elsikora/nestjs-aws-parameter-store-config 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@elsikora/nestjs-aws-parameter-store-config 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^22.13.0 || >=24.11.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@elsikora/nestjs-aws-parameter-store-config 可以商用吗?

@elsikora/nestjs-aws-parameter-store-config 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@elsikora/nestjs-aws-parameter-store-config 的下载量有多少?

根据 npm 官方下载统计,@elsikora/nestjs-aws-parameter-store-config 在 2026/10/14 – 2026/11/12 这 30 天内被下载 6,675 次,日均约 223 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@elsikora/nestjs-aws-parameter-store-config 还在维护吗?

最新版本 3.0.0 发布于 2026/11/03(10 天前);至今共发布 32 个版本,其中过去 12 个月发布了 8 个;首次发布于 2024/03/17。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。