Loading...
Loading...
Compare original and translation side by side
console.logconsole.lognpm auditnpm audit// Feature flag check
const flags = await getFeatureFlags(userId);
if (flags.taskSharing) {
// New feature: task sharing
return <TaskSharingPanel task={task} />;
}
// Default: existing behavior
return null;1. DEPLOY with flag OFF → Code is in production but inactive
2. ENABLE for team/beta → Internal testing in production environment
3. GRADUAL ROLLOUT → 5% → 25% → 50% → 100% of users
4. MONITOR at each stage → Watch error rates, performance, user feedback
5. CLEAN UP → Remove flag and dead code path after full rollout// Feature flag check
const flags = await getFeatureFlags(userId);
if (flags.taskSharing) {
// New feature: task sharing
return <TaskSharingPanel task={task} />;
}
// Default: existing behavior
return null;1. DEPLOY with flag OFF → Code is in production but inactive
2. ENABLE for team/beta → Internal testing in production environment
3. GRADUAL ROLLOUT → 5% → 25% → 50% → 100% of users
4. MONITOR at each stage → Watch error rates, performance, user feedback
5. CLEAN UP → Remove flag and dead code path after full rollout1. DEPLOY to staging
└── Full test suite in staging environment
└── Manual smoke test of critical flows
2. DEPLOY to production (feature flag OFF)
└── Verify deployment succeeded (health check)
└── Check error monitoring (no new errors)
3. ENABLE for team (flag ON for internal users)
└── Team uses the feature in production
└── 24-hour monitoring window
4. CANARY rollout (flag ON for 5% of users)
└── Monitor error rates, latency, user behavior
└── Compare metrics: canary vs. baseline
└── 24-48 hour monitoring window
5. GRADUAL increase (25% → 50% → 100%)
└── Same monitoring at each step
└── Ability to roll back to previous percentage at any point
6. FULL rollout (flag ON for all users)
└── Monitor for 1 week
└── Clean up feature flag1. DEPLOY to staging
└── Full test suite in staging environment
└── Manual smoke test of critical flows
2. DEPLOY to production (feature flag OFF)
└── Verify deployment succeeded (health check)
└── Check error monitoring (no new errors)
3. ENABLE for team (flag ON for internal users)
└── Team uses the feature in production
└── 24-hour monitoring window
4. CANARY rollout (flag ON for 5% of users)
└── Monitor error rates, latency, user behavior
└── Compare metrics: canary vs. baseline
└── 24-48 hour monitoring window
5. GRADUAL increase (25% → 50% → 100%)
└── Same monitoring at each step
└── Ability to roll back to previous percentage at any point
6. FULL rollout (flag ON for all users)
└── Monitor for 1 week
└── Clean up feature flagApplication metrics:
├── Error rate (total and by endpoint)
├── Response time (p50, p95, p99)
├── Request volume
├── Active users
└── Key business metrics (conversion, engagement)
Infrastructure metrics:
├── CPU and memory utilization
├── Database connection pool usage
├── Disk space
├── Network latency
└── Queue depth (if applicable)
Client metrics:
├── Core Web Vitals (LCP, INP, CLS)
├── JavaScript errors
├── API error rates from client perspective
└── Page load timeApplication metrics:
├── Error rate (total and by endpoint)
├── Response time (p50, p95, p99)
├── Request volume
├── Active users
└── Key business metrics (conversion, engagement)
Infrastructure metrics:
├── CPU and memory utilization
├── Database connection pool usage
├── Disk space
├── Network latency
└── Queue depth (if applicable)
Client metrics:
├── Core Web Vitals (LCP, INP, CLS)
├── JavaScript errors
├── API error rates from client perspective
└── Page load time// Set up error boundary with reporting
class ErrorBoundary extends React.Component {
componentDidCatch(error: Error, info: React.ErrorInfo) {
// Report to error tracking service
reportError(error, {
componentStack: info.componentStack,
userId: getCurrentUser()?.id,
page: window.location.pathname,
});
}
render() {
if (this.state.hasError) {
return <ErrorFallback onRetry={() => this.setState({ hasError: false })} />;
}
return this.props.children;
}
}
// Server-side error reporting
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
reportError(err, {
method: req.method,
url: req.url,
userId: req.user?.id,
});
// Don't expose internals to users
res.status(500).json({
error: { code: 'INTERNAL_ERROR', message: 'Something went wrong' },
});
});// Set up error boundary with reporting
class ErrorBoundary extends React.Component {
componentDidCatch(error: Error, info: React.ErrorInfo) {
// Report to error tracking service
reportError(error, {
componentStack: info.componentStack,
userId: getCurrentUser()?.id,
page: window.location.pathname,
});
}
render() {
if (this.state.hasError) {
return <ErrorFallback onRetry={() => this.setState({ hasError: false })} />;
}
return this.props.children;
}
}
// Server-side error reporting
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
reportError(err, {
method: req.method,
url: req.url,
userId: req.user?.id,
});
// Don't expose internals to users
res.status(500).json({
error: { code: 'INTERNAL_ERROR', message: 'Something went wrong' },
});
});1. Check health endpoint returns 200
2. Check error monitoring dashboard (no new error types)
3. Check latency dashboard (no regression)
4. Test the critical user flow manually
5. Verify logs are flowing and readable
6. Confirm rollback mechanism works (dry run if possible)1. Check health endpoint returns 200
2. Check error monitoring dashboard (no new error types)
3. Check latency dashboard (no regression)
4. Test the critical user flow manually
5. Verify logs are flowing and readable
6. Confirm rollback mechanism works (dry run if possible)undefinedundefinedgit revert <commit> && git pushgit revert <commit> && git pushnpx prisma migrate rollbacknpx prisma migrate rollbackundefinedundefined| Rationalization | Reality |
|---|---|
| "It works in staging, it'll work in production" | Production has different data, traffic patterns, and edge cases. Monitor after deploy. |
| "We don't need feature flags for this" | Every feature benefits from a kill switch. Even "simple" changes can break things. |
| "Monitoring is overhead" | Not having monitoring means you discover problems from user complaints instead of dashboards. |
| "We'll add monitoring later" | Add it before launch. You can't debug what you can't see. |
| "Rolling back is admitting failure" | Rolling back is responsible engineering. Shipping a broken feature is the failure. |
| 自我合理化借口 | 实际情况 |
|---|---|
| “在 staging 环境能正常运行,生产环境肯定也没问题” | 生产环境的数据、流量模式和边缘情况都与 staging 不同,部署后必须监控。 |
| “这个功能不需要Feature Flag” | 每个功能都需要一个紧急关闭开关,即使是「简单」的变更也可能出问题。 |
| “监控是额外负担” | 没有监控意味着你只能通过用户反馈发现问题,而不是通过仪表盘提前预警。 |
| “我们之后再添加监控” | 上线前就应该配置好监控,你无法调试看不到的问题。 |
| “回滚等于承认失败” | 回滚是负责任的工程实践,发布有问题的功能才是失败。 |