nestjs-redis
A NestJS module that wraps ioredis to manage Redis and Redis Cluster connections through dependency injection.
Repository Health
Technical Analysis
@liaoliaots/nestjs-redis is a NestJS module that wraps ioredis to provide first-class Redis and Redis Cluster support inside Nest’s dependency-injection system. It registers one or more named Redis connections through RedisModule.forRoot()/forRootAsync(), then exposes them via an injectable RedisService that retrieves clients by namespace with either a throwing (getOrThrow) or nil-safe (getOrNil) accessor.
The module manages connection lifecycle automatically, closing clients on application shutdown when closeClient is enabled, logging connection-state changes, and supporting both single-instance and array-of-namespace configurations. A parallel ClusterModule/ClusterService pair provides the equivalent API for Redis Cluster deployments, and a sibling @liaoliaots/nestjs-redis-health package layers Terminus health-indicator support on top.
What You Get
- RedisModule.forRoot() / forRootAsync() for synchronous or async (factory/class/existing-provider) configuration
- An injectable RedisService with getOrThrow()/getOrNil() namespace-based client lookup
- ClusterModule/ClusterService offering the same DI-friendly API for Redis Cluster
- Automatic client shutdown via NestJS’s OnApplicationShutdown lifecycle hook when closeClient is enabled
- Connection lifecycle hooks (readyLog, errorLog, beforeCreate) for observability and customization
Common Use Cases
- Injecting a shared Redis client into services for caching, session storage, or rate limiting
- Running multiple named Redis connections (e.g. cache vs. queue) in one Nest application
- Connecting to Redis Cluster deployments through the same DI pattern used for standalone Redis
- Wiring Redis-backed adapters for other libraries (e.g. throttler storage) using the exposed ioredis client
Under The Hood
Architecture
The module follows Nest’s DynamicModule pattern: RedisModule.forRoot()/forRootAsync() assemble a provider array (REDIS_OPTIONS, REDIS_MERGED_OPTIONS, REDIS_CLIENTS, RedisService) built up through small factory functions in redis.providers.ts, keeping option-merging, client-map construction, and service wiring as separate, composable units rather than one large constructor. RedisModule itself implements OnApplicationShutdown, pulling the merged options and client map back out via ModuleRef to quit() every managed connection and strip listeners on teardown. The cluster/ subtree mirrors this exact shape (constants, providers, module, service, interfaces) for ClusterModule, so the two connection types share a design language without sharing runtime code, and path aliases (@/utils, @/errors, @/interfaces) keep cross-module imports flat.
Tech Stack
Written in TypeScript against @nestjs/common/@nestjs/core ^10.0.0 and ioredis ^5.0.0 as peer dependencies, with tslib as the only runtime dependency. The repo is a pnpm workspace monorepo (packages/redis, packages/node-redis, packages/redis-health) built with tsc + tsc-alias for path-alias rewriting, linted with ESLint 9’s flat config (typescript-eslint recommendedTypeChecked + stylistic, eslint-plugin-jest, Prettier integration), and gated by Husky + commitlint (Conventional Commits) plus lint-staged on commit.
Code Quality
Every source file under lib/ has a matching .spec.ts, and the README displays 100% statements/branches/functions/lines coverage badges backed by Jest + ts-jest; a separate test/jest-e2e.json config supports end-to-end suites. Failure modes are explicit rather than swallowed: ConnectionNotFoundError and MissingConfigurationsError are dedicated error classes surfaced instead of generic throws, and small type-guard utilities (isError, isDirectInstanceOf) centralize runtime type checks used throughout the shutdown and provider logic. Naming and typing are consistent (strict interfaces for module options, typed provider factories), and tsc --noEmit runs as its own lint step alongside ESLint.
API Design
Getting started requires only RedisModule.forRoot({ config: {...} }) in one module import and @Inject-free constructor injection of RedisService elsewhere — minimal boilerplate for the common case. The dual getOrThrow/getOrNil accessors give callers an explicit choice between fail-fast and nil-safe retrieval instead of one ambiguous method, namespaces default sensibly to a single implicit connection, and forRootAsync supports useFactory/useClass/useExisting so configuration can be sourced from a ConfigService without extra glue code. Extensive JSDoc on every public option and versioned docs under docs/ (v2 through latest) make the configuration surface easy to discover.
Used by 2 apps in this directory
Bigcapital
Invoicing Finance
Self-hostable double-entry accounting platform with invoicing, inventory, multi-currency, and real-time financial reporting for small and medium businesses.
Laudspeaker
Marketing · Automation
Open-source customer engagement platform for building visual, event-triggered messaging journeys across email, SMS, push, in-app, and webhooks.