@mayday.sh/sdk
v0.2.1
Published
Third-party API dependency monitoring SDK
Downloads
609
Maintainers
Readme
@mayday.sh/sdk
Know when your third-party APIs break before your users do.
Mayday monitors every outbound HTTP call your Node.js application makes — Stripe, OpenAI, Twilio, AWS, and 100+ services — and alerts you the moment something degrades.
One SDK. Three lines of code. Real-time dependency health.
import { init } from '@mayday.sh/sdk'
init({ apiKey: 'md_live_...' })
// That's it. Every outbound HTTP call is now monitored.Why Mayday?
When a third-party API your app depends on starts failing, you need to know immediately — and you need to know if it's them or you.
- Status pages are slow. Vendor status pages lag 15-30+ minutes behind real incidents and miss partial degradations.
- Full APM is overkill. Datadog/New Relic cost $100K+/year and require multi-day instrumentation projects.
- Mayday is focused. One SDK, one job: monitor your outbound API calls and answer "is it us or them?" in seconds.
How It Works
- The SDK intercepts all outbound HTTP requests at the transport layer
- Metrics are aggregated in-process into 1-minute buckets (no per-request export)
- Compressed metric batches are sent to the Mayday backend every 30 seconds
- The backend runs anomaly detection and alerts you via Slack, Discord, or email
No request/response bodies are ever captured. URLs are sanitized in-process before any data leaves your application. See Privacy.
Installation
npm install @mayday.sh/sdkRequires Node.js 18+.
Quick Start
1. Get an API key
Sign up at app.mayday.sh — one click with GitHub, no credit card.
2. Add to your app
Express / Fastify / any Node.js server:
// At the top of your entry file (server.ts, index.ts, app.ts)
import { init } from '@mayday.sh/sdk'
init({ apiKey: process.env.DEPWATCH_API_KEY })
// ... rest of your app
import express from 'express'
const app = express()Next.js (instrumentation hook):
// instrumentation.ts (project root)
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs') {
const { init } = await import('@mayday.sh/sdk')
init({ apiKey: process.env.DEPWATCH_API_KEY })
}
}Important: Call init() as early as possible, before any HTTP calls are made.
3. Deploy and check the dashboard
Make some requests in your app and open your Mayday dashboard. You'll see every third-party service auto-discovered and categorized within 60 seconds.
Configuration
init({
// Required: your API key
apiKey: 'md_live_...',
// Disable monitoring (e.g., in test environments)
// Default: true
enabled: process.env.NODE_ENV !== 'test',
// How often to export metrics (milliseconds)
// Default: 30000 (30 seconds). Minimum: 5000.
flushIntervalMs: 30000,
// Domains to exclude from monitoring
// The backend domain (api.mayday.sh) is auto-excluded.
ignoreDomains: ['localhost', 'your-internal-api.local'],
// Log every intercepted call to console (for verifying setup)
// Default: false
debug: true,
// Custom backend URL (for self-hosted or local dev)
// Default: 'https://api.mayday.sh'
endpoint: 'http://localhost:3001',
})What's Captured
For each outbound HTTP request, the SDK records:
| Field | Example | Purpose |
|-------|---------|---------|
| Domain | api.stripe.com | Service identification |
| Endpoint | /v1/charges/{id} | Endpoint-level metrics |
| Method | POST | Endpoint grouping |
| Status code | 200 | Error rate calculation |
| Total duration | 145ms | Latency tracking |
| DNS time | 2ms | "Is it us or them?" |
| TCP connect time | 15ms | Network diagnosis |
| TLS time | 20ms | TLS issue detection |
| Time to first byte | 108ms | Server processing time |
| Error flag | false | Error detection |
These fields are aggregated into 1-minute statistical buckets (count, min, max, P50, P95, P99, status code distribution) before export. Raw per-request data never leaves your application.
What's NOT Captured
- Request bodies
- Response bodies
- Authorization headers
- Cookie values
- Query parameter values (keys are kept for endpoint grouping, values are stripped)
- Any PII
Privacy
URL sanitization runs in-process before any data leaves your application:
Input: https://api.stripe.com/v1/charges/ch_3MqAyZ2eZvKYlo/capture?expand[]=balance_transaction
Output: domain: api.stripe.com
endpoint: /v1/charges/{id}/capture?expand=- UUIDs →
{id} - Numeric IDs →
{id} - Base62/Base64 tokens →
{id} - Query values → stripped (keys preserved)
Performance
The SDK is designed to be invisible in production:
| Metric | Target | How | |--------|--------|-----| | Latency overhead | <0.1ms per call | Event listeners, no sync work in request path | | CPU | <0.5% of one core | Aggregation only, no serialization per request | | Memory | <10MB RSS | Bounded ring buffer, DDSketch percentiles | | Network | <50KB/min exported | 1-min aggregation reduces volume 100-500x | | Startup | <50ms | Channel subscription + timer setup |
The export timer uses setInterval().unref() — it won't prevent your process from exiting.
Interception
The SDK uses two complementary interception strategies:
diagnostics_channel(primary): Subscribes to undici's diagnostic events. Covers nativefetch()in Node 18+ and direct undici usage. Zero monkey-patching.http.requestpatch (fallback): Wraps Node'shttp.request()andhttps.request(). Covers axios, got, node-fetch v2, and any library using the built-in http module.
These are disjoint code paths — undici does not use Node's http module. Both are always enabled. Zero double-counting.
Graceful Shutdown
import { shutdown } from '@mayday.sh/sdk'
process.on('SIGTERM', async () => {
await shutdown() // Final metric flush + restore patched functions
process.exit(0)
})Troubleshooting
"I don't see any services on the dashboard"
- Verify
debug: trueis set — you should see log lines like:[mayday] POST api.stripe.com/v1/charges → 200 (145.2ms) - Check that
enabledisn't set tofalse - Ensure the API key starts with
md_live_(notmd_test_) - Check that the backend is reachable (default:
https://api.mayday.sh)
"Some HTTP calls aren't being captured"
- The SDK captures calls made after
init()is called. Make sureinit()runs before your app makes any requests. - Calls to
localhostor your own backend aren't captured by default — but you can checkignoreDomainsto be sure.
"I'm worried about performance impact"
- Set
debug: truetemporarily and watch the console. The overhead is sub-millisecond. - The SDK only records metadata (timing + status code). No request/response bodies are ever processed.
- Memory is bounded: max 10 slots × 1000 endpoints regardless of traffic volume.
API
init(config: MaydayConfig): void
Initialize the SDK. Call once at application startup.
shutdown(): Promise<void>
Gracefully shut down: performs a final metric flush and restores all patched functions.
MaydayConfig
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiKey | string | (required) | API key (md_live_* or md_test_*) |
| enabled | boolean | true | Kill switch |
| flushIntervalMs | number | 30000 | Export interval (min 5000) |
| ignoreDomains | string[] | [] | Domains to exclude |
| debug | boolean | false | Log intercepted calls |
| endpoint | string | https://api.mayday.sh | Backend URL |
| appId | string | null | App identifier (multi-app) |
License
MIT
