@kayouris/nestjs-maintenance
v1.0.0
Published
A NestJS dynamic module for maintenance mode management
Maintainers
Readme
NestJS Maintenance Mode Module
A lightweight, zero-config NestJS dynamic module that gracefully puts your API into maintenance mode with a single line of code. When active, it automatically intercepts every incoming request and returns an HTTP 503 Service Unavailable response — without touching a single controller. Specific routes or entire controllers can be exempted via the @BypassMaintenance() decorator, and the state can be toggled at runtime with no restart required.
✨ Features
- 🧠 In-memory state management — no database or external service required
- 🔄 Sync & Async module registration —
forRoot()andforRootAsync()with full factory/class/useExisting support - 🌍 Global guard auto-registration — registered via
APP_GUARDso it covers every route automatically - 🏷️
@BypassMaintenance()decorator — opt-out at the method or controller level with a single decorator - ⚡ Ultra-fast — built and tested with Bun
- ✅ 100% test coverage — unit and integration tests with
bun:testand@nestjs/testing - 🤝 NestJS 10 & 11 compatible via peer dependencies
📦 Installation
# Bun (recommended)
bun add @kayouris/nestjs-maintenance
# NPM
npm install @kayouris/nestjs-maintenance
# Yarn
yarn add @kayouris/nestjs-maintenancePeer dependencies — ensure these are installed in your project:
@nestjs/common,@nestjs/core,rxjs
🚀 Quick Start
Synchronous registration
// app.module.ts
import { Module } from '@nestjs/common';
import { MaintenanceModule } from '@kayouris/nestjs-maintenance';
@Module({
imports: [
MaintenanceModule.forRoot({
enabledInitially: false, // start with maintenance OFF
}),
],
})
export class AppModule {}Asynchronous registration
Ideal when the initial state comes from an environment variable or external config service:
// app.module.ts
import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { MaintenanceModule } from '@kayouris/nestjs-maintenance';
@Module({
imports: [
ConfigModule.forRoot(),
MaintenanceModule.forRootAsync({
imports: [ConfigModule],
useFactory: (config: ConfigService) => ({
enabledInitially: config.get<boolean>('MAINTENANCE_MODE', false),
}),
inject: [ConfigService],
}),
],
})
export class AppModule {}Bypassing maintenance on specific routes
Use @BypassMaintenance() on a single handler or an entire controller class to exempt it from the guard:
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { BypassMaintenance } from '@kayouris/nestjs-maintenance';
@Controller()
export class AppController {
// ✅ Always reachable — even when maintenance is ON
@BypassMaintenance()
@Get('health')
healthCheck() {
return { status: 'ok' };
}
// 🔒 Returns HTTP 503 when maintenance is active
@Get('products')
getProducts() {
return [];
}
}
// You can also exempt an entire controller:
@BypassMaintenance()
@Controller('admin')
export class AdminController { /* all routes bypass maintenance */ }🔧 Dynamic Toggling
Inject MaintenanceService anywhere in your application to control maintenance mode programmatically at runtime — no restart needed:
// admin.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { BypassMaintenance, MaintenanceService } from '@kayouris/nestjs-maintenance';
@BypassMaintenance() // admin routes must remain accessible during maintenance
@Controller('admin/maintenance')
export class AdminController {
constructor(private readonly maintenanceService: MaintenanceService) {}
@Post('enable')
enable() {
this.maintenanceService.setMaintenanceMode(true);
return { maintenanceActive: true };
}
@Post('disable')
disable() {
this.maintenanceService.setMaintenanceMode(false);
return { maintenanceActive: false };
}
@Post('toggle')
toggle() {
const newState = this.maintenanceService.toggleMaintenanceMode();
return { maintenanceActive: newState };
}
@Get('status')
status() {
return { maintenanceActive: this.maintenanceService.isMaintenanceEnabled() };
}
}MaintenanceService API
| Method | Return | Description |
|---|---|---|
| setMaintenanceMode(enabled: boolean) | void | Explicitly enable or disable maintenance mode |
| isMaintenanceEnabled() | boolean | Returns the current maintenance state |
| toggleMaintenanceMode() | boolean | Flips the state and returns the new value |
🧪 Local Example
A fully working demo application lives in the example/ directory. It exposes three endpoints to let you observe the guard in action:
| Method | Route | Behaviour |
|---|---|---|
| GET | /public | @BypassMaintenance() — always returns 200 |
| GET | /secure | Returns 503 when maintenance is ON |
| POST | /maintenance/toggle | Flips maintenance mode ON / OFF |
Run it locally:
# 1. Build the library from the repo root
bun run build
# 2. Install example dependencies and start the server
cd example
bun install
bun run startThe server will start on http://localhost:3000. You can then exercise it with curl:
# Secure endpoint is accessible (maintenance OFF)
curl http://localhost:3000/secure
# Enable maintenance
curl -X POST http://localhost:3000/maintenance/toggle
# Secure endpoint is now blocked (503)
curl http://localhost:3000/secure
# Public route always passes through
curl http://localhost:3000/public
# Disable maintenance
curl -X POST http://localhost:3000/maintenance/toggle📄 License
Distributed under the MIT License. See LICENSE for details.
