协作头脑风暴
brainstorming
在实现前澄清需求、探索设计选择,并形成清晰的开发方向。
posthog-prod-checklist【开发与工程】Run a fail-safe production-readiness review for PostHog instrumentation, flags, secrets, privacy, delivery, and rollback. Use when enabling a new production integration or major SDK change. Trigger with "PostHog production checklist", "PostHog go-live", or "review PostHog launch".
独立 GitHub 快照 · 自动分类 · 以原作者文档为准
name: posthog-prod-checklist description: | Run a fail-safe production-readiness review for PostHog instrumentation, flags, secrets, privacy, delivery, and rollback. Use when enabling a new production integration or major SDK change. Trigger with "PostHog production checklist", "PostHog go-live", or "review PostHog launch". argument-hint: "[project-path] [release-ref]" allowed-tools: Read, Bash(kubectl:), Bash(curl:), Grep version: 1.14.0 license: MIT author: Jeremy Longshore jeremy@intentsolutions.io tags:
Production readiness verification for PostHog integrations. Covers SDK configuration hardening, graceful degradation when PostHog is unavailable, health check endpoints, proper shutdown hooks for serverless, and rollback procedures.
phc_ keyUse Read to inspect the relevant configuration and implementation before proposing changes. Use Grep to locate initialization, capture, flag, and credential boundaries.
SDK Configuration:
api_host set to correct region (us.i.posthog.com or eu.i.posthog.com)capture_pageview: false if using SPA with manual pageview trackingcapture_pageleave: true for session duration accuracyposthog-sdk-patterns)posthog.debug() disabled in production (guarded by NODE_ENV)autocapture configured to exclude noisy elementsServer-Side:
posthog.shutdown() called in SIGTERM handler and serverless function cleanuppersonalApiKey for server-side local evaluationflushAt and flushInterval tuned (default 20/10s is fine for most apps)Security:
phx_) never in client bundles or NEXT_PUBLIC_ vars.env files in .gitignore// lib/posthog-production.ts
import { PostHog } from 'posthog-node';
const posthog = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
host: process.env.POSTHOG_HOST || 'https://us.i.posthog.com',
personalApiKey: process.env.POSTHOG_FEATURE_FLAGS_SECURE_API_KEY,
flushAt: 20,
flushInterval: 10000,
requestTimeout: 10000,
maxRetries: 3,
});
// Graceful shutdown
async function shutdown() {
await posthog.shutdown();
process.exit(0);
}
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);
// PostHog should never break your app — wrap all calls
function safeCapture(distinctId: string, event: string, properties?: Record<string, any>) {
try {
posthog.capture({ distinctId, event, properties });
} catch (error) {
// Log but never throw — analytics should not crash your app
console.error('[PostHog] Capture failed:', (error as Error).message);
}
}
async function safeGetFlag(flagKey: string, userId: string, defaultValue: boolean = false): Promise<boolean> {
try {
const result = await posthog.isFeatureEnabled(flagKey, userId);
return result ?? defaultValue;
} catch (error) {
console.error('[PostHog] Flag evaluation failed:', (error as Error).message);
return defaultValue; // Always return safe default
}
}
// api/health.ts (Next.js API route or Express handler)
// getPostHogDeliverySnapshot() reads application-owned counters maintained by
// the capture wrapper; it does not send a synthetic event on every health check.
export async function GET() {
const delivery = getPostHogDeliverySnapshot();
const degraded = delivery.errorRatio > delivery.reviewedErrorRatio
|| delivery.oldestQueuedEventMs > delivery.reviewedQueueAgeMs
|| delivery.flagFallbackRatio > delivery.reviewedFlagFallbackRatio;
return Response.json({
status: degraded ? 'degraded' : 'healthy',
checks: {
capture_delivery: delivery.captureStatus,
queue_age_ms: delivery.oldestQueuedEventMs,
flag_fallback_ratio: delivery.flagFallbackRatio,
last_success_at: delivery.lastSuccessAt,
},
}, { status: degraded ? 503 : 200 });
}
// For Vercel Edge Functions, AWS Lambda, etc.
import { PostHog } from 'posthog-node';
export async function handler(request: Request) {
// Create client per invocation in serverless (or use module-level singleton)
const posthog = new PostHog(process.env.NEXT_PUBLIC_POSTHOG_KEY!, {
host: 'https://us.i.posthog.com',
flushAt: 1, // Flush immediately in serverless
flushInterval: 0, // Don't wait
});
try {
posthog.capture({
distinctId: getUserId(request),
event: 'api_called',
properties: { endpoint: new URL(request.url).pathname },
});
const result = await doWork(request);
return Response.json(result);
} finally {
// CRITICAL: Always flush before function exits
await posthog.shutdown();
}
}
set -euo pipefail
: "${POSTHOG_PUBLIC_HOST:?Set the regional ingestion host for this project}"
: "${POSTHOG_PRIVATE_HOST:?Set the matching private API host}"
# 1. Verify PostHog is reachable from the release environment.
curl -sf "$POSTHOG_PUBLIC_HOST/healthz" && echo "PostHog: OK" || echo "PostHog: UNREACHABLE"
# 2. Verify the public project token through the non-capture flags endpoint.
curl -s -X POST "$POSTHOG_PUBLIC_HOST/flags?v=2" \
-H 'Content-Type: application/json' \
-d "{\"api_key\":\"$NEXT_PUBLIC_POSTHOG_KEY\",\"distinct_id\":\"deploy-check\"}" | jq '{flags, errorsParsingFlags}'
# 3. Verify private API access only when the integration requires it.
curl -sf "$POSTHOG_PRIVATE_HOST/api/projects/$POSTHOG_PROJECT_ID/" \
-H "Authorization: Bearer $POSTHOG_PERSONAL_API_KEY" | jq '.name' && echo "Admin API: OK"
Verify event delivery in a dedicated test project or with an explicitly approved synthetic production event. A 200 response confirms receipt and payload shape, not final ingestion; inspect quota_limited, ingestion warnings, and the resulting named event.
| Alert | Trigger | Severity | Action |
|---|---|---|---|
| PostHog capture failing | Application delivery error SLO breached | P3 | Check API host, queue, flush, and ingestion warnings |
| Flag evaluation breaches the service SLO | Reviewed service threshold | P2 | Inspect local evaluation, cache state, and remote fallback |
| Events not appearing | Expected event freshness SLO breached | P2 | Check shutdown() is called, verify flush and warnings |
| Admin API 401 | Personal key rejected | P1 | Rotate key in PostHog settings |
set -euo pipefail
# Quick rollback if PostHog causes issues
# Option 1: Disable PostHog via env var
kubectl set env deployment/app POSTHOG_ENABLED=false
kubectl rollout restart deployment/app
# Option 2: Roll back deployment
kubectl rollout undo deployment/app
kubectl rollout status deployment/app
Before enabling production capture, verify the regional host, project-token scope, consent behavior, server lifecycle, flag defaults, proxy routes, release owner, and kill switch. Use a controlled test identity and report each check as pass, fail, or not applicable with evidence.
See official PostHog references for current authority and verification boundaries.
For version upgrades, see posthog-upgrade-migration.