@real_rinku01/drift-monitor
v1.0.0
Published
Zero-config API contract drift monitor — detect mismatches between OpenAPI specs and actual API responses before they reach production.
Maintainers
Readme
🔍 drift-monitor
Zero-Config API Contract Drift Monitor
Detect API contract mismatches before they reach production.
The Problem
Backend developers frequently change API response shapes — database columns, field types, enum values, nullable fields — without updating the OpenAPI spec, Swagger docs, or notifying frontend/mobile teams.
The result? Production bugs.
// Swagger says: // Backend actually returns:
{ {
"phoneNumber": "string" "phoneNumber": 987654321 ← 💥
} }Frontend crashes. Mobile crashes. The team notices only after deployment.
The Solution
drift-monitor is a lightweight Node.js middleware that plugs into your Express or Fastify application and automatically:
- 🔍 Intercepts every request and response
- 📋 Matches to the corresponding OpenAPI schema
- ✅ Validates payloads against the contract
- 🚨 Detects contract drift in real-time
- 📊 Generates readable diffs with severity levels
- 📣 Notifies developers via Slack, Discord, webhooks, or console
All with < 2ms average overhead and zero configuration required.
Quick Start
Installation
npm install drift-monitorExpress
import express from 'express';
import { createExpressMiddleware } from 'drift-monitor';
const app = express();
app.use(express.json());
// One line to add drift monitoring
app.use(createExpressMiddleware({
openapi: { specPath: './openapi.yaml' }
}));
app.get('/users', (req, res) => {
res.json([{ id: 1, name: 'Alice', phoneNumber: 12345 }]); // ← drift detected!
});
app.listen(3000);Fastify
import Fastify from 'fastify';
import { createFastifyPlugin } from 'drift-monitor';
const fastify = Fastify();
fastify.register(createFastifyPlugin, {
openapi: { specPath: './openapi.yaml' }
});
fastify.listen({ port: 3000 });Features
| Feature | Status | |---------|--------| | Express middleware | ✅ | | Fastify plugin | ✅ | | OpenAPI 3.0+ support | ✅ | | YAML & JSON specs | ✅ | | Remote URL specs | ✅ | | Hot-reload specs | ✅ | | Request validation | ✅ | | Response validation | ✅ | | Type mismatch detection | ✅ | | Missing field detection | ✅ | | Enum violation detection | ✅ | | Nullable mismatch detection | ✅ | | Nested object validation | ✅ | | Array validation | ✅ | | oneOf/allOf/anyOf | ✅ | | Severity classification | ✅ | | Breaking change detection | ✅ | | Ignore rules (glob/regex) | ✅ | | Slack notifications | ✅ | | Discord notifications | ✅ | | Webhook notifications | ✅ | | Console notifications | ✅ | | File logging (NDJSON) | ✅ | | Prometheus metrics | ✅ | | Sampling | ✅ | | Async validation | ✅ | | LRU validator cache | ✅ | | Plugin system | ✅ | | CLI tools | ✅ | | Docker support | ✅ | | GitHub Actions CI | ✅ |
Architecture
┌─────────────────────────────────────────────────────┐
│ Host Application │
│ ┌──────────┐ ┌───────────┐ ┌──────────────┐ │
│ │ Incoming │──▶│ Drift │──▶│ App Handler │ │
│ │ Request │ │ Monitor │ │ │ │
│ └──────────┘ │ Middleware │ └──────┬───────┘ │
│ └─────┬─────┘ │ │
│ │ ┌─────▼───────┐ │
│ │ │ Response │ │
│ │ │ Interceptor│ │
│ │ └─────┬───────┘ │
│ │ │ │
│ ┌─────▼────────────────▼─────┐ │
│ │ Validation Orchestrator │ │
│ │ ┌─────────┐ ┌────────────┐ │ │
│ │ │ Route │ │ AJV │ │ │
│ │ │ Matcher │ │ Engine │ │ │
│ │ └─────────┘ └────────────┘ │ │
│ └──────────────┬───────────────┘ │
│ │ │
│ ┌─────────────▼──────────────┐ │
│ │ Notification Manager │ │
│ │ Slack│Discord│Webhook│File │ │
│ └────────────────────────────┘ │
└─────────────────────────────────────────────────────┘Configuration
# .drift-monitor.yaml
openapi:
specPath: ./openapi.yaml
watchForChanges: true
validation:
enabled: true
sampleRate: 1.0 # Validate 100% of requests
mode: async # Non-blocking validation
request: true
response: true
notifications:
debounceMs: 5000 # Deduplicate alerts per endpoint
console:
enabled: true
slack:
enabled: true
webhookUrl: ${SLACK_WEBHOOK_URL}
discord:
enabled: false
webhookUrl: ""
ignore:
endpoints:
- /health
- /metrics
methods:
- OPTIONS
- HEAD
statusCodes:
- 304
cache:
maxSize: 1000
logging:
level: info
format: jsonEnvironment variables use DRIFT_MONITOR_ prefix with double-underscore for nesting:
DRIFT_MONITOR_VALIDATION__SAMPLE_RATE=0.5
DRIFT_MONITOR_NOTIFICATIONS__SLACK__ENABLED=true
DRIFT_MONITOR_NOTIFICATIONS__SLACK__WEBHOOK_URL=https://hooks.slack.com/...CLI
# Initialize config
drift-monitor init
# Check spec and config
drift-monitor doctor
# Validate OpenAPI spec
drift-monitor validate --spec ./openapi.yaml
# Watch for spec changes
drift-monitor watch --spec ./openapi.yaml
# Run performance benchmark
drift-monitor benchmark --iterations 100000Drift Detection Example
When drift is detected, you get detailed output:
🚨 API Contract Drift Detected
══════════════════════════════════════════════════════
🟠 [BREAKING] /phoneNumber
├─ Expected: string
├─ Received: integer
├─ Severity: HIGH
└─ Type: TYPE_MISMATCH
🟡 [non-breaking] /extraField
├─ Expected: field not to be present
├─ Received: unexpected field found
├─ Severity: WARNING
└─ Type: UNEXPECTED_FIELD
──────────────────────────────────────────────────────
Total: 2 | Breaking: 1 | Non-breaking: 1Plugin System
Extend drift-monitor with custom plugins:
import { Plugin, PluginContext, HookType } from 'drift-monitor';
const myPlugin: Plugin = {
name: 'my-custom-plugin',
version: '1.0.0',
initialize(context: PluginContext) {
context.registerHook(HookType.ON_DRIFT, async (payload) => {
// Custom drift handling logic
console.log('Custom plugin detected drift:', payload);
});
},
};Prometheus Metrics
When metrics are enabled, the following are exported:
| Metric | Type | Description |
|--------|------|-------------|
| drift_monitor_validations_total | Counter | Total validations |
| drift_monitor_drifts_total | Counter | Total drifts detected |
| drift_monitor_alerts_total | Counter | Total alerts sent |
| drift_monitor_validation_duration_seconds | Histogram | Validation latency |
| drift_monitor_cache_size | Gauge | Cached validators |
| drift_monitor_cache_hit_ratio | Gauge | Cache hit rate |
Performance
Target: < 2ms average validation latency
The validation engine uses:
- Compiled AJV validators (compile-once, cache-forever)
- LRU cache for route matching
- Async validation queue (non-blocking)
- Request sampling for high-traffic endpoints
Run benchmarks:
npm run benchmark
# or
drift-monitor benchmark --iterations 100000Project Structure
src/
├── adapters/ # Express & Fastify adapters
├── cache/ # LRU cache implementation
├── cli/ # CLI commands
├── config/ # Configuration system
├── core/ # Domain logic & orchestration
├── diff/ # Diff engine & formatters
├── logger/ # Pino-based logging
├── metrics/ # Prometheus metrics
├── middleware/ # Request/response interception
├── parser/ # OpenAPI spec parsing
├── plugins/ # Plugin system
├── types/ # TypeScript type definitions
├── utils/ # Shared utilities
├── validators/ # AJV validation engine
├── webhooks/ # Notification adapters
└── index.ts # Public APIContributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Development
git clone https://github.com/yourusername/drift-monitor.git
cd drift-monitor
npm install
npm run dev # Watch mode
npm test # Run tests
npm run lint # Lint
npm run benchmark # BenchmarksLicense
MIT © drift-monitor contributors
Built with ❤️ for developer experience.
Stop shipping contract bugs. Start monitoring drift.
