Deepgram Production Checklist
Overview
Comprehensive go-live checklist for Deepgram integrations. Covers singleton client, health checks, Prometheus metrics, alert rules, error handling, and a phased go-live timeline.
Production Readiness Matrix
| Category |
Item |
Status |
| Auth |
Production API key with scoped permissions |
[ ] |
| Auth |
Key stored in secret manager (not env file) |
[ ] |
| Auth |
Key rotation schedule (90-day) configured |
[ ] |
| Auth |
Fallback key provisioned and tested |
[ ] |
| Resilience |
Retry with exponential backoff on 429/5xx |
[ ] |
| Resilience |
Circuit breaker for cascade failure prevention |
[ ] |
| Resilience |
Request timeout set (30s pre-recorded, 10s TTS) |
[ ] |
| Resilience |
Graceful degradation when API unavailable |
[ ] |
| Performance |
Singleton client (not creating per-request) |
[ ] |
| Performance |
Concurrency limited (50-80% of plan limit) |
[ ] |
| Performance |
Audio preprocessed (16kHz mono for best results) |
[ ] |
| Performance |
Large files use callback URL (async) |
[ ] |
| Monitoring |
Health check endpoint testing Deepgram API |
[ ] |
| Monitoring |
Prometheus metrics: latency, error rate, usage |
[ ] |
| Monitoring |
Alerts: error rate >5%, latency >10s, circuit open |
[ ] |
| Security |
PII redaction enabled if handling sensitive audio |
[ ] |
| Security |
Audio URLs validated (HTTPS, no private IPs) |
[ ] |
| Security |
Audit logging on all operations |
[ ] |
Instructions
Step 1: Production Singleton Client
import { createClient, DeepgramClient } from '@deepgram/sdk';
class ProductionDeepgram {
private static client: DeepgramClient | null = null;
static getClient(): DeepgramClient {
if (!this.client) {
const key = process.env.DEEPGRAM_API_KEY;
if (!key) throw new Error('DEEPGRAM_API_KEY required for production');
this.client = createClient(key);
}
return this.client;
}
// Force re-init (for key rotation)
static reset() { this.client = null; }
}
Step 2: Health Check Endpoint
import express from 'express';
import { createClient } from '@deepgram/sdk';
const app = express();
const deepgram = createClient(process.env.DEEPGRAM_API_KEY!);
app.get('/health', async (req, res) => {
const start = Date.now();
try {
// Test API connectivity by listing projects
const { error } = await deepgram.manage.getProjects();
const latency = Date.now() - start;
if (error) {
return res.status(503).json({
status: 'unhealthy',
deepgram: 'error',
error: error.message,
latency_ms: latency,
});
}
res.json({
status: 'healthy',
deepgram: 'connected',
latency_ms: latency,
timestamp: new Date().toISOString(),
});
} catch (err: any) {
res.status(503).json({
status: 'unhealthy',
deepgram: 'unreachable',
error: err.message,
latency_ms: Date.now() - start,
});
}
});
Step 3: Prometheus Metrics
import { Counter, Histogram, Gauge, Registry } from 'prom-client';
const registry = new Registry();
const transcriptionRequests = new Counter({
name: 'deepgram_requests_total',
help: 'Total Deepgram API requests',
labelNames: ['method', 'model', 'status'],
registers: [registry],
});
const transcriptionLatency = new Histogram({
name: 'deepgram_latency_seconds',
help: 'Deepgram API request latency',
labelNames: ['method', 'model'],
buckets: [0.5, 1, 2, 5, 10, 30],
registers: [registry],
});
const audioProcessed = new Counter({
name: 'deepgram_audio_seconds_total',
help: 'Total audio seconds processed',
labelNames: ['model'],
registers: [registry],
});
const activeConnections = new Gauge({
name: 'deepgram_active_connections',
help: 'Active WebSocket connections',
registers: [registry],
});
// Instrumented transcription
async function instrumentedTranscribe(url: string, model = 'nova-3') {
const timer = transcriptionLatency.startTimer({ method: 'prerecorded', model });
try {
const { result, error } = await deepgram.listen.prerecorded.transcribeUrl(
{ url }, { model, smart_format: true }
);
timer();
transcriptionRequests.inc({ method: 'prerecorded', model, status: error ? 'error' : 'ok' });
if (result?.metadata?.duration) {
audioProcessed.inc({ model }, result.metadata.duration);
}
if (error) throw error;
return result;
} catch (err) {
timer();
transcriptionRequests.inc({ method: 'prerecorded', model, status: 'error' });
throw err;
}
}
// Expose metrics endpoint
app.get('/metrics', async (req, res) => {
res.set('Content-Type', registry.contentType);
res.send(await registry.metrics());
});
Step 4: Alert Rules (Prometheus/AlertManager)
groups:
- name: deepgram
rules:
- alert: DeepgramHighErrorRate
expr: rate(deepgram_requests_total{status="error"}[5m]) / rate(deepgram_requests_total[5m]) > 0.05
for: 5m
labels:
severity: critical
annotations:
summary: "Deepgram error rate > 5%"
- alert: DeepgramHighLatency
expr: histogram_quantile(0.95, rate(deepgram_latency_seconds_bucket[5m])) > 10
for: 5m
labels:
severity: warning
annotations:
summary: "Deepgram P95 latency > 10s"
- alert: DeepgramHealthCheckFailed
expr: up{job="deepgram-service"} == 0
for: 2m
labels:
severity: critical
annotations:
summary: "Deepgram health check failed for 2+ minutes"
Step 5: Error Handling Wrapper
async function safeTranscribe(url: string, options: Record<string, any> = {}) {
const timeout = options.timeout ?? 30000;
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), timeout);
try {
const result = await Promise.race([
instrumentedTranscribe(url, options.model ?? 'nova-3'),
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Transcription timeout')), timeout)
),
]);
clearTimeout(timeoutId);
return result;
} catch (err: any) {
clearTimeout(timeoutId);
// Log structured error
console.error(JSON.stringify({
level: 'error',
service: 'deepgram',
message: err.message,
url: url.substring(0, 100),
timestamp: new Date().toISOString(),
}));
throw err;
}
}
Step 6: Go-Live Timeline
| Phase |
When |
Actions |
| D-7 |
1 week before |
Load test at 2x expected volume, security review |
| D-3 |
3 days before |
Smoke test with production key, verify all alerts fire |
| D-1 |
Day before |
Confirm on-call rotation, validate dashboards |
| D-0 |
Launch |
Shadow mode (10% traffic), monitoring open |
| D+1 |
Day after |
Review error rate, latency, verify no anomalies |
| D+7 |
1 week after |
Full traffic, tune alert thresholds based on baselines |
Output
- Singleton client with reset capability
- Health check endpoint with latency reporting
- Prometheus metrics (requests, latency, audio, connections)
- AlertManager rules for error rate, latency, availability
- Timeout-safe transcription wrapper
- Phased go-live timeline
Error Handling
| Issue |
Cause |
Solution |
| Health check 503 |
API key expired |
Rotate key, check secret manager |
| Metrics not scraped |
Wrong port/path |
Verify Prometheus target config |
| Alert storms |
Thresholds too tight |
Add for: duration, tune values |
| Timeout on large files |
Sync mode too slow |
Switch to callback URL pattern |
Resources
1---2name: deepgram-prod-checklist3description: |4 Execute Deepgram production deployment checklist.5 Use when preparing for production launch, auditing production readiness,6 or verifying deployment configurations.7 Trigger: "deepgram production", "deploy deepgram", "deepgram prod checklist",8 "deepgram go-live", "production ready deepgram".9allowed-tools: Read, Write, Edit, Grep, Bash(curl:*)10version: 1.0.011license: MIT12author: Jeremy Longshore <jeremy@intentsolutions.io>13compatible-with: claude-code, codex, openclaw14tags: [saas, deepgram, deployment, production]1516---1718# Deepgram Production Checklist1920## Overview21Comprehensive go-live checklist for Deepgram integrations. Covers singleton client, health checks, Prometheus metrics, alert rules, error handling, and a phased go-live timeline.2223## Production Readiness Matrix2425| Category | Item | Status |26|----------|------|--------|27| **Auth** | Production API key with scoped permissions | [ ] |28| **Auth** | Key stored in secret manager (not env file) | [ ] |29| **Auth** | Key rotation schedule (90-day) configured | [ ] |30| **Auth** | Fallback key provisioned and tested | [ ] |31| **Resilience** | Retry with exponential backoff on 429/5xx | [ ] |32| **Resilience** | Circuit breaker for cascade failure prevention | [ ] |33| **Resilience** | Request timeout set (30s pre-recorded, 10s TTS) | [ ] |34| **Resilience** | Graceful degradation when API unavailable | [ ] |35| **Performance** | Singleton client (not creating per-request) | [ ] |36| **Performance** | Concurrency limited (50-80% of plan limit) | [ ] |37| **Performance** | Audio preprocessed (16kHz mono for best results) | [ ] |38| **Performance** | Large files use callback URL (async) | [ ] |39| **Monitoring** | Health check endpoint testing Deepgram API | [ ] |40| **Monitoring** | Prometheus metrics: latency, error rate, usage | [ ] |41| **Monitoring** | Alerts: error rate >5%, latency >10s, circuit open | [ ] |42| **Security** | PII redaction enabled if handling sensitive audio | [ ] |43| **Security** | Audio URLs validated (HTTPS, no private IPs) | [ ] |44| **Security** | Audit logging on all operations | [ ] |4546## Instructions4748### Step 1: Production Singleton Client4950```typescript51import { createClient, DeepgramClient } from '@deepgram/sdk';5253class ProductionDeepgram {54 private static client: DeepgramClient | null = null;5556 static getClient(): DeepgramClient {57 if (!this.client) {58 const key = process.env.DEEPGRAM_API_KEY;59 if (!key) throw new Error('DEEPGRAM_API_KEY required for production');60 this.client = createClient(key);61 }62 return this.client;63 }6465 // Force re-init (for key rotation)66 static reset() { this.client = null; }67}68```6970### Step 2: Health Check Endpoint7172```typescript73import express from 'express';74import { createClient } from '@deepgram/sdk';7576const app = express();77const deepgram = createClient(process.env.DEEPGRAM_API_KEY!);7879app.get('/health', async (req, res) => {80 const start = Date.now();81 try {82 // Test API connectivity by listing projects83 const { error } = await deepgram.manage.getProjects();84 const latency = Date.now() - start;8586 if (error) {87 return res.status(503).json({88 status: 'unhealthy',89 deepgram: 'error',90 error: error.message,91 latency_ms: latency,92 });93 }9495 res.json({96 status: 'healthy',97 deepgram: 'connected',98 latency_ms: latency,99 timestamp: new Date().toISOString(),100 });101 } catch (err: any) {102 res.status(503).json({103 status: 'unhealthy',104 deepgram: 'unreachable',105 error: err.message,106 latency_ms: Date.now() - start,107 });108 }109});110```111112### Step 3: Prometheus Metrics113114```typescript115import { Counter, Histogram, Gauge, Registry } from 'prom-client';116117const registry = new Registry();118119const transcriptionRequests = new Counter({120 name: 'deepgram_requests_total',121 help: 'Total Deepgram API requests',122 labelNames: ['method', 'model', 'status'],123 registers: [registry],124});125126const transcriptionLatency = new Histogram({127 name: 'deepgram_latency_seconds',128 help: 'Deepgram API request latency',129 labelNames: ['method', 'model'],130 buckets: [0.5, 1, 2, 5, 10, 30],131 registers: [registry],132});133134const audioProcessed = new Counter({135 name: 'deepgram_audio_seconds_total',136 help: 'Total audio seconds processed',137 labelNames: ['model'],138 registers: [registry],139});140141const activeConnections = new Gauge({142 name: 'deepgram_active_connections',143 help: 'Active WebSocket connections',144 registers: [registry],145});146147// Instrumented transcription148async function instrumentedTranscribe(url: string, model = 'nova-3') {149 const timer = transcriptionLatency.startTimer({ method: 'prerecorded', model });150 try {151 const { result, error } = await deepgram.listen.prerecorded.transcribeUrl(152 { url }, { model, smart_format: true }153 );154 timer();155 transcriptionRequests.inc({ method: 'prerecorded', model, status: error ? 'error' : 'ok' });156 if (result?.metadata?.duration) {157 audioProcessed.inc({ model }, result.metadata.duration);158 }159 if (error) throw error;160 return result;161 } catch (err) {162 timer();163 transcriptionRequests.inc({ method: 'prerecorded', model, status: 'error' });164 throw err;165 }166}167168// Expose metrics endpoint169app.get('/metrics', async (req, res) => {170 res.set('Content-Type', registry.contentType);171 res.send(await registry.metrics());172});173```174175### Step 4: Alert Rules (Prometheus/AlertManager)176177```yaml178groups:179 - name: deepgram180 rules:181 - alert: DeepgramHighErrorRate182 expr: rate(deepgram_requests_total{status="error"}[5m]) / rate(deepgram_requests_total[5m]) > 0.05183 for: 5m184 labels:185 severity: critical186 annotations:187 summary: "Deepgram error rate > 5%"188189 - alert: DeepgramHighLatency190 expr: histogram_quantile(0.95, rate(deepgram_latency_seconds_bucket[5m])) > 10191 for: 5m192 labels:193 severity: warning194 annotations:195 summary: "Deepgram P95 latency > 10s"196197 - alert: DeepgramHealthCheckFailed198 expr: up{job="deepgram-service"} == 0199 for: 2m200 labels:201 severity: critical202 annotations:203 summary: "Deepgram health check failed for 2+ minutes"204```205206### Step 5: Error Handling Wrapper207208```typescript209async function safeTranscribe(url: string, options: Record<string, any> = {}) {210 const timeout = options.timeout ?? 30000;211212 const controller = new AbortController();213 const timeoutId = setTimeout(() => controller.abort(), timeout);214215 try {216 const result = await Promise.race([217 instrumentedTranscribe(url, options.model ?? 'nova-3'),218 new Promise((_, reject) =>219 setTimeout(() => reject(new Error('Transcription timeout')), timeout)220 ),221 ]);222 clearTimeout(timeoutId);223 return result;224 } catch (err: any) {225 clearTimeout(timeoutId);226 // Log structured error227 console.error(JSON.stringify({228 level: 'error',229 service: 'deepgram',230 message: err.message,231 url: url.substring(0, 100),232 timestamp: new Date().toISOString(),233 }));234 throw err;235 }236}237```238239### Step 6: Go-Live Timeline240241| Phase | When | Actions |242|-------|------|---------|243| D-7 | 1 week before | Load test at 2x expected volume, security review |244| D-3 | 3 days before | Smoke test with production key, verify all alerts fire |245| D-1 | Day before | Confirm on-call rotation, validate dashboards |246| D-0 | Launch | Shadow mode (10% traffic), monitoring open |247| D+1 | Day after | Review error rate, latency, verify no anomalies |248| D+7 | 1 week after | Full traffic, tune alert thresholds based on baselines |249250## Output251- Singleton client with reset capability252- Health check endpoint with latency reporting253- Prometheus metrics (requests, latency, audio, connections)254- AlertManager rules for error rate, latency, availability255- Timeout-safe transcription wrapper256- Phased go-live timeline257258## Error Handling259| Issue | Cause | Solution |260|-------|-------|----------|261| Health check 503 | API key expired | Rotate key, check secret manager |262| Metrics not scraped | Wrong port/path | Verify Prometheus target config |263| Alert storms | Thresholds too tight | Add `for:` duration, tune values |264| Timeout on large files | Sync mode too slow | Switch to `callback` URL pattern |265266## Resources267- [Deepgram Production Guide](https://developers.deepgram.com/docs/production-guide)268- [Prometheus Best Practices](https://prometheus.io/docs/practices/)269- [Deepgram SLA](https://deepgram.com/sla)270