Skip to main content
Back to Blog
Guide
2026-02-23

Testing in Production -- Canary Deployments, Feature Flags, and Synthetic Monitoring

Complete guide to testing in production safely. Covers canary deployments, feature flags, synthetic monitoring, observability-driven testing, and progressive rollout strategies.

Testing in production used to be the ultimate taboo. "You never test in production" was treated as an unbreakable commandment -- right up there with "don't deploy on Fridays" and "always write tests before shipping." But the reality of modern software delivery has turned that commandment on its head. Today, the most reliable engineering teams in the world -- Netflix, Google, Amazon, Shopify, Stripe -- all test in production deliberately and systematically. They have discovered what many teams are now learning: pre-production environments can never fully replicate the complexity of production, and the only way to truly know if your software works is to observe it under real conditions with real users. Testing in production is no longer reckless. When done with the right strategies -- canary deployments, feature flags, synthetic monitoring, and observability-driven testing -- it becomes one of the most powerful tools in your quality assurance arsenal.


Key Takeaways

  • Testing in production is a disciplined practice that uses controlled techniques like canary deployments, feature flags, and synthetic monitoring to validate software under real-world conditions -- it is not about skipping pre-production testing
  • Canary deployments route a small percentage of traffic to new code, letting you monitor real metrics before promoting to the full fleet -- catching issues that staging environments miss
  • Feature flags decouple deployment from release, allowing you to test new features with internal users or a small cohort before exposing them to everyone -- with instant kill switches for rollback
  • Synthetic monitoring runs scheduled test scripts against production endpoints 24/7, catching regressions before real users encounter them
  • Progressive rollout strategies combine multiple techniques into a structured promotion path from internal testing through beta, canary, and gradual percentage-based rollout
  • Observability replaces some traditional testing -- distributed tracing, structured logging, and anomaly detection give you continuous validation that your system is behaving correctly

Why Test in Production?

The fundamental problem with pre-production testing is that staging is a lie. No matter how much effort you invest in making your staging environment mirror production, it will always differ in ways that matter. Consider the gaps:

Data scale and distribution. Your staging database has thousands of rows. Production has billions. Query plans behave differently. Indexes that work perfectly on small datasets degrade under production volumes. Edge cases that exist in real user data -- unicode characters in names, addresses with special formatting, accounts with decades of history -- simply do not exist in sanitized staging data.

Traffic patterns. Staging gets a handful of requests from your CI pipeline and a few manual testers. Production handles thousands of concurrent users with bursty, unpredictable traffic patterns. Race conditions, connection pool exhaustion, and cache stampedes only manifest under real load. You might run load tests against staging, but synthetic load never perfectly replicates the chaotic patterns of real users.

Third-party integrations. Payment gateways, email providers, SMS services, analytics platforms, CDN configurations, DNS resolution -- all of these behave differently in production. Third-party sandbox environments have different rate limits, different response times, and different failure modes than their production counterparts. An integration that works flawlessly against a sandbox API can fail in production because of a rate limit you never hit in testing.

Infrastructure differences. Production runs across multiple availability zones with real load balancers, CDN edge nodes, WAF rules, and network policies. Staging typically runs in a single zone with simplified networking. TLS certificate issues, DNS propagation delays, and cross-region latency are invisible in staging.

Configuration drift. Despite infrastructure-as-code and GitOps, production configurations drift from staging over time. Feature flags, A/B test configurations, environment variables, and runtime settings accumulate differences that change application behavior in subtle ways.

The shift from "never test in prod" to "test safely in prod" is not about abandoning pre-production testing. You still write unit tests, integration tests, and E2E tests. You still run them in CI. But you recognize that passing all pre-production tests is necessary but not sufficient. The final validation must happen where it matters: in production, with real users, under real conditions. The key word is "safely" -- and that is what the rest of this guide is about.


Canary Deployments

A canary deployment is a production testing strategy where you route a small percentage of real traffic to a new version of your application while the majority of traffic continues hitting the current stable version. The name comes from the coal mining practice of bringing a canary into the mine -- if the canary stopped singing, miners knew the air was toxic. In software, the canary release is your early warning system.

How Canary Deployments Work

The architecture of a canary deployment involves three components:

  1. Load balancer or service mesh -- Routes traffic between the stable version and the canary version based on configured weights
  2. Canary version -- A small number of instances (often just one or two) running the new code
  3. Monitoring and analysis -- Automated comparison of metrics between the canary and the stable version

A typical canary deployment flow looks like this:

1. Deploy new version to canary instances (1-5% of fleet)
2. Route 1% of production traffic to canary
3. Monitor key metrics for 15-30 minutes
4. If metrics are healthy, increase to 5%, then 10%, then 25%
5. At each stage, compare canary metrics against baseline
6. If any metric degrades beyond threshold, automatic rollback
7. If all stages pass, promote canary to full fleet

Key Metrics to Monitor During Canary

The metrics you monitor during a canary deployment determine whether the release promotes or rolls back. Track these categories:

Metric CategoryWhat to MonitorRollback Threshold
Error rateHTTP 5xx responses, unhandled exceptions, error log volume> 1% increase over baseline
Latencyp50, p95, p99 response times> 20% increase at p99
SaturationCPU usage, memory, connection pool utilization> 80% utilization
Business metricsConversion rate, checkout completions, API success rate> 2% decrease
Custom signalsFeature-specific metrics relevant to the changeDefined per release

Canary Deployment Tools

Several tools and platforms support canary deployment testing:

  • Kubernetes-native: Argo Rollouts, Flagger, and Istio provide weighted routing and automated canary analysis directly in your cluster
  • Cloud provider: AWS CodeDeploy, Google Cloud Deploy, and Azure Deployment Slots all support canary strategies
  • Service mesh: Istio, Linkerd, and Consul Connect enable fine-grained traffic splitting at the network level
  • Feature delivery platforms: LaunchDarkly, Split.io, and Harness support percentage-based rollouts with built-in metric analysis

The most important principle of canary deployment testing is automated rollback. A canary that requires a human to decide whether to roll back is a canary that will fail at 3 AM on a Saturday. Configure your canary analysis to automatically roll back when metrics breach predefined thresholds. Human judgment is for the initial threshold configuration, not for real-time rollback decisions.


Feature Flags for Safe Testing

Feature flags (also called feature toggles) are a production testing strategy that decouples deployment from release. With feature flags, you can deploy code to production that is invisible to users until you explicitly enable it. This gives you the ability to test new features in production with controlled audiences -- internal employees, beta users, or a small percentage of traffic -- before exposing them to everyone.

Feature Flag Testing Patterns

Feature flag testing enables several powerful patterns:

Internal dogfooding. Enable a feature only for employees using your product. Your team experiences the feature under real production conditions -- real data, real integrations, real performance -- days or weeks before any external user sees it. This catches issues that staging environments miss because your employees interact with the product differently than synthetic test scripts.

Beta cohort testing. Enable a feature for a self-selected group of users who opt into early access. These users expect rough edges and are more likely to report issues. You get real user feedback and real usage data before a broad rollout.

Percentage-based rollout. Enable a feature for 1% of users, monitor metrics, increase to 5%, monitor again, and continue until you reach 100%. This is similar to a canary deployment but operates at the feature level rather than the deployment level, giving you finer-grained control.

Kill switch pattern. Wrap any risky code path in a feature flag so you can disable it instantly without a deployment. If a new recommendation algorithm starts returning irrelevant results, you flip the flag and revert to the previous algorithm in seconds -- no CI pipeline, no deployment, no rollback.

Feature Flag in a Test Suite

You can also write automated tests that verify behavior under different flag states:

// feature-flag-testing.spec.ts
import { test, expect } from '@playwright/test';

test.describe('Checkout V2 feature flag testing', () => {
  test('shows legacy checkout when flag is disabled', async ({ page }) => {
    // Set feature flag cookie or use API to disable flag
    await page.context().addCookies([
      { name: 'ff_checkout_v2', value: 'false', domain: 'localhost', path: '/' },
    ]);

    await page.goto('/cart');
    await page.click('[data-testid="checkout-button"]');

    // Legacy checkout should render
    await expect(page.locator('[data-testid="legacy-checkout"]')).toBeVisible();
    await expect(page.locator('[data-testid="checkout-v2"]')).not.toBeVisible();
  });

  test('shows new checkout when flag is enabled', async ({ page }) => {
    await page.context().addCookies([
      { name: 'ff_checkout_v2', value: 'true', domain: 'localhost', path: '/' },
    ]);

    await page.goto('/cart');
    await page.click('[data-testid="checkout-button"]');

    // V2 checkout should render
    await expect(page.locator('[data-testid="checkout-v2"]')).toBeVisible();
    await expect(page.locator('[data-testid="legacy-checkout"]')).not.toBeVisible();
  });

  test('kill switch disables feature mid-session', async ({ page }) => {
    // Start with flag enabled
    await page.context().addCookies([
      { name: 'ff_checkout_v2', value: 'true', domain: 'localhost', path: '/' },
    ]);
    await page.goto('/cart');
    await expect(page.locator('[data-testid="checkout-v2"]')).toBeVisible();

    // Simulate kill switch -- disable flag
    await page.context().addCookies([
      { name: 'ff_checkout_v2', value: 'false', domain: 'localhost', path: '/' },
    ]);
    await page.reload();

    // Should gracefully fall back to legacy
    await expect(page.locator('[data-testid="legacy-checkout"]')).toBeVisible();
  });
});

Feature Flag Management Tools

The most widely used feature flag testing platforms include:

  • LaunchDarkly -- Enterprise-grade feature management with targeting rules, experimentation, and metric integration
  • Unleash -- Open-source feature flag server with a strong community and self-hosting option
  • Flagsmith -- Open-source with remote config, A/B testing, and multi-environment support
  • Custom flags -- Simple database-backed or config-file flags for teams that do not need a dedicated platform

Regardless of the tool, the critical practice is flag hygiene. Every feature flag should have an owner, an expiration date, and a plan for removal. Flags that live forever become technical debt. A feature that has been fully rolled out for three months does not need a flag anymore -- remove it.


Synthetic Monitoring

Synthetic monitoring is a production testing strategy where automated scripts simulate user interactions against your live production environment on a scheduled basis. Unlike real user monitoring (which passively observes actual users), synthetic monitoring proactively executes predefined test scenarios -- typically every 1 to 5 minutes -- to detect issues before real users encounter them.

How Synthetic Monitoring Works

A synthetic monitor is essentially an automated test that runs on a schedule against production. It simulates a critical user journey -- logging in, searching for a product, completing a checkout -- and reports the result as pass/fail along with performance metrics. If the monitor fails, it triggers an alert.

Here is an example synthetic monitoring script for a critical user journey using Checkly:

// synthetic-checkout-monitor.ts
import { test, expect } from '@playwright/test';

test('Critical path: search to checkout', async ({ page }) => {
  // Step 1: Load homepage
  await page.goto('https://yourapp.com');
  await expect(page).toHaveTitle(/YourApp/);

  // Step 2: Search for a product
  await page.fill('[data-testid="search-input"]', 'wireless headphones');
  await page.press('[data-testid="search-input"]', 'Enter');
  await expect(page.locator('[data-testid="search-results"]')).toBeVisible();

  // Step 3: Select first result
  await page.click('[data-testid="product-card"]:first-child');
  await expect(page.locator('[data-testid="product-detail"]')).toBeVisible();

  // Step 4: Add to cart
  await page.click('[data-testid="add-to-cart"]');
  await expect(page.locator('[data-testid="cart-count"]')).toHaveText('1');

  // Step 5: Begin checkout
  await page.click('[data-testid="checkout-button"]');
  await expect(page.locator('[data-testid="checkout-form"]')).toBeVisible();

  // Step 6: Verify payment form loads
  await expect(page.locator('[data-testid="payment-section"]')).toBeVisible();
});

Synthetic Monitoring Platforms

The leading synthetic monitoring tools include:

  • Datadog Synthetics -- Browser tests, API tests, and multistep API tests with global locations and integrated alerting
  • Checkly -- Developer-focused monitoring using Playwright scripts, with monitoring-as-code support via CLI and Terraform
  • Grafana Synthetic Monitoring -- Open-source option integrated with Grafana dashboards and alerting
  • New Relic Synthetics -- Scripted browser monitors and API checks with detailed performance breakdowns
  • Pingdom -- Simple uptime and page speed monitoring for teams that need basic coverage

Alerting on Synthetic Failures

The value of synthetic monitoring depends entirely on your alerting configuration. A synthetic test that fails silently is worse than no test at all -- it gives you false confidence. Configure alerts with these principles:

  • Alert on consecutive failures, not single failures. A single failed run could be a transient network blip. Alert after 2-3 consecutive failures to reduce noise
  • Route alerts to the right team. Checkout monitor failures go to the payments team. Search monitor failures go to the search team. A single on-call channel for all synthetic alerts leads to alert fatigue
  • Include context in alerts. The alert should include the failing step, a screenshot, the response time breakdown, and a link to the full trace. An alert that says "Checkout monitor failed" is far less useful than one that says "Checkout monitor failed at Step 5: payment form did not load within 10 seconds -- screenshot attached"
  • Track alert trends. If a synthetic monitor fails intermittently every Tuesday morning, that is a signal worth investigating -- perhaps a scheduled batch job is competing for database resources

Real User Monitoring (RUM)

While synthetic monitoring proactively tests production, Real User Monitoring passively collects performance and error data from actual users as they interact with your application. RUM is the complement to synthetic monitoring -- together, they provide a complete picture of production health.

What RUM Captures

RUM libraries like the web-vitals JavaScript library, Sentry, and Datadog RUM instrument your application to capture:

  • Core Web Vitals -- Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). These metrics directly impact user experience and SEO ranking
  • JavaScript errors -- Unhandled exceptions, promise rejections, and console errors captured with full stack traces and user context
  • Network requests -- API call timing, failure rates, and payload sizes from the user's perspective
  • User sessions -- Session replay tools record a video-like reconstruction of user interactions, letting you see exactly what the user experienced when an error occurred

Using RUM as a Testing Signal

RUM data becomes a powerful production testing signal when you treat it as a continuous quality metric:

RUM-Based Quality Gates:
- LCP > 2.5s for > 5% of users      --> alert: performance regression
- JS error rate > 0.5%                --> alert: code quality issue
- API failure rate > 1% for endpoint  --> alert: backend regression
- CLS > 0.1 for > 10% of page views  --> alert: layout instability

Error tracking platforms like Sentry, Bugsnag, and Rollbar aggregate RUM error data and correlate it with deployments. When you deploy a new version and Sentry shows a spike in a new error type, you have immediate production test feedback -- something broke, and you know exactly which release introduced it. This is testing in production through continuous observation rather than explicit test execution.

Session replay tools like LogRocket, FullStory, and Sentry Session Replay let you watch recordings of real user sessions. When a user reports a bug, you can watch exactly what happened instead of trying to reproduce it locally. This is an incredibly powerful debugging tool that also serves as a form of production testing -- you are observing real user behavior and identifying issues that no scripted test would catch.


Progressive Rollout Strategies

A progressive rollout combines canary deployments, feature flags, and monitoring into a structured promotion path. Rather than deploying directly to 100% of users, you move through defined stages with explicit criteria for advancement and rollback.

Rollout Stages

StageAudienceDurationCriteria to AdvanceRollback Trigger
InternalEmployees only1-3 daysNo critical bugs, positive internal feedbackAny P0 bug
BetaOpt-in users (1-5%)3-7 daysError rate < baseline + 0.1%, no new crash signaturesError rate > baseline + 0.5%
CanaryRandom 1% of all users1-2 daysAll metrics within 5% of baselineAny metric > 20% deviation
Gradual 10%Random 10% of all users1 dayAll metrics within 5% of baselineAny metric > 15% deviation
Gradual 25%Random 25% of all users1 dayAll metrics within 3% of baselineAny metric > 10% deviation
Gradual 50%Random 50% of all users4-8 hoursAll metrics within 2% of baselineAny metric > 10% deviation
Full rollout100% of usersOngoingMonitoring continues post-rolloutSignificant regression detected

Rollback Decision Framework

Every production testing strategy needs a clear rollback decision framework. Ambiguity during an incident leads to delayed rollbacks and extended user impact. Define these criteria in advance:

Automatic rollback triggers -- These conditions trigger an immediate, automated rollback with no human decision required:

  • Error rate exceeds 5x baseline
  • p99 latency exceeds 3x baseline
  • More than 10 unique new crash signatures in 5 minutes
  • Any data corruption detected
  • Health check failures on more than 50% of instances

Manual rollback triggers -- These conditions page the on-call engineer for a human decision:

  • Error rate exceeds 2x baseline but is below automatic threshold
  • Business metric (conversion rate, revenue) drops by more than 3%
  • Customer reports of a specific issue exceed 5 within 30 minutes
  • Canary analysis is inconclusive after the maximum observation window

Do not rollback -- These conditions are expected and should not trigger rollback:

  • Transient metric fluctuations that resolve within 2 minutes
  • Known issues documented in the release notes
  • Metric changes that are expected consequences of the feature (e.g., a new feature that intentionally adds a step to checkout will increase checkout time)

Chaos Engineering in Production

Chaos engineering takes testing in production to the next level by deliberately injecting faults into your production systems to verify that your resilience mechanisms work under real conditions. While canary deployments test new code, chaos engineering tests your existing infrastructure and failure handling.

Controlled Fault Injection

Production chaos experiments must be carefully scoped to minimize blast radius:

  • Network faults -- Introduce latency, packet loss, or DNS resolution failures between specific services to verify timeout and retry configurations
  • Instance termination -- Kill individual pods or VMs to verify that auto-scaling, load balancing, and health checks work correctly
  • Dependency failures -- Simulate a third-party API outage to verify that circuit breakers, fallbacks, and graceful degradation work as expected
  • Resource exhaustion -- Simulate CPU throttling, memory pressure, or disk space exhaustion to verify that your alerts fire and your systems degrade gracefully

GameDay Exercises

A GameDay is a structured team exercise where engineers deliberately inject failures into production (or a production-like environment) while the team practices their incident response. GameDays combine chaos engineering with incident response training:

  1. Define the scenario -- "The primary database becomes read-only due to disk full"
  2. Assign roles -- Incident commander, communications lead, technical responders
  3. Inject the fault -- Using chaos engineering tools, trigger the scenario
  4. Respond and observe -- The team responds as they would during a real incident, while observers note what works and what does not
  5. Post-mortem -- Review the exercise, document findings, and create action items

GameDays build confidence that your team can handle real incidents because they have practiced under controlled conditions. They also expose gaps in runbooks, alerting, and automation that you would otherwise only discover during a real outage.

For a deeper exploration of chaos engineering principles, tools like Chaos Monkey and Litmus, and step-by-step guidance on running experiments, see our dedicated chaos engineering guide.


Observability as Testing

The most advanced form of testing in production is treating observability itself as a testing mechanism. Instead of writing explicit test assertions, you instrument your system so thoroughly that anomalous behavior is automatically detected and surfaced. This approach -- sometimes called observability-driven testing or production testing through instrumentation -- turns your monitoring stack into a continuous testing platform.

Distributed Tracing

Distributed tracing with OpenTelemetry gives you end-to-end visibility into every request as it flows through your system. Each trace captures the full call chain -- which services were called, how long each call took, whether any call failed, and what data was passed between services.

Tracing becomes a testing signal when you define expectations about trace behavior:

  • Latency budgets -- A checkout request should complete in under 2 seconds. If a trace shows the payment service taking 1.8 seconds when it normally takes 200ms, that is a regression detected without any explicit test
  • Call graph validation -- A search request should hit the cache first and only query the database on a cache miss. If traces show the search service bypassing the cache, you have detected a behavioral regression
  • Error propagation -- When a downstream service returns an error, the upstream service should handle it gracefully. Traces that show unhandled errors propagating to the user indicate a missing error handler

Structured Logging

Structured logging -- emitting logs as JSON objects with consistent fields -- enables automated analysis that unstructured text logs cannot support. When every log entry includes fields like service, request_id, user_id, duration_ms, and status, you can:

  • Detect anomalies in error rates per endpoint, per service, per region
  • Identify slow queries by monitoring duration_ms distributions
  • Correlate errors across services using request_id
  • Track deployment impact by filtering logs by version

Metric Anomaly Detection

Modern monitoring platforms support anomaly detection that automatically identifies when a metric deviates from its historical pattern. Instead of setting static thresholds (alert if latency > 500ms), anomaly detection learns the normal pattern for each metric -- including daily and weekly cycles -- and alerts when the metric behaves abnormally.

This is effectively automated testing in production: the system continuously compares current behavior against learned baselines and reports deviations. A latency spike at 2 PM on Tuesday might be normal (batch processing window) while the same spike at 2 AM on Saturday is anomalous. Anomaly detection handles this context automatically, reducing false alerts while catching real regressions.

The combination of distributed tracing, structured logging, and anomaly detection creates a continuous validation layer that runs 24/7 without any explicit test scripts. Your production environment is constantly being tested by its own instrumentation.


Automate Production Testing with AI Agents

AI coding agents can help you implement and maintain production testing strategies. With specialized QA skills installed, your agent gains expert knowledge about smoke test design, monitoring scripts, and production validation patterns.

Install production-focused QA skills with a single command:

# Production smoke test suite -- comprehensive post-deployment validation
npx @qaskills/cli add production-smoke-suite

# Website audit -- performance, accessibility, SEO, and best practices
npx @qaskills/cli add audit-website

Additional skills that support production testing workflows:

  • page-speed-critic -- Analyzes Core Web Vitals and provides actionable performance recommendations, directly supporting your RUM quality gates
  • dead-link-detector -- Crawls your production site for broken links, 404 pages, and redirect chains -- a form of synthetic monitoring for content integrity

These skills teach your AI agent the patterns and best practices covered in this guide. When you ask your agent to write a synthetic monitoring script, a canary deployment configuration, or a feature flag test, it draws on expert QA knowledge to produce production-ready code.

Browse all available QA skills at qaskills.sh/skills or get started with the installation guide. For related testing strategies, see our guide on smoke testing vs sanity testing -- smoke tests are the foundation of any production testing strategy.


Frequently Asked Questions

Is testing in production the same as not testing before production?

No. Testing in production is an addition to pre-production testing, not a replacement. You still write unit tests, integration tests, and E2E tests that run in CI/CD. You still run them in staging. Testing in production adds an additional layer of validation that catches issues pre-production testing cannot -- issues related to data scale, traffic patterns, third-party integrations, and real user behavior. The teams that test in production most effectively are typically the same teams with the strongest pre-production test suites. Production testing handles the last mile that staging cannot cover.

How do you prevent testing in production from affecting real users?

Multiple techniques minimize user impact. Feature flags let you hide new features from most users while testing with a small cohort. Canary deployments route only 1-5% of traffic to new code, limiting the blast radius of any issue. Synthetic monitoring uses automated scripts rather than real user traffic. Dark launches process production traffic through new code paths without returning the results to users -- you compare the new output against the existing output to verify correctness. And automatic rollback mechanisms revert changes within seconds when metrics degrade, limiting the window of impact to a small fraction of users over a short time period.

What is the difference between canary deployment and blue-green deployment?

A blue-green deployment maintains two identical production environments (blue and green). You deploy to the inactive environment, run verification tests, and then switch all traffic from the active environment to the new one. A canary deployment gradually shifts a small percentage of traffic to the new version while monitoring metrics, incrementally increasing the percentage over time. The key difference is in risk exposure: blue-green is all-or-nothing (you switch 100% of traffic at once), while canary is incremental (you start with 1% and slowly increase). Canary deployments give you more production testing time and smaller blast radius, but they require more sophisticated traffic routing infrastructure. Many teams use both -- blue-green for infrastructure changes and canary for application code changes.

How much does testing in production cost compared to maintaining staging environments?

For many organizations, testing in production is actually cheaper than maintaining a full staging environment that accurately mirrors production. Staging environments that replicate production data volumes, third-party integrations, multi-region architecture, and traffic patterns are expensive to build and maintain. They also require ongoing effort to prevent configuration drift. The infrastructure cost of canary deployments is minimal -- you add a few extra instances during the rollout window. Feature flag platforms like LaunchDarkly have per-seat pricing. Synthetic monitoring tools like Checkly are typically $200-500/month for comprehensive coverage. Compare that to the cost of a full production-mirror staging environment with anonymized production data -- which can easily run into thousands per month. The real ROI, however, is in the defects you catch that staging would miss, each of which could cost thousands in incident response and customer impact.

What are the biggest risks of testing in production?

The primary risks are data corruption, user-facing errors, and security exposure. Data corruption can occur if a buggy code path writes incorrect data to production databases -- mitigate this with database rollback strategies, write-behind patterns, and feature flags that control write paths separately from read paths. User-facing errors are mitigated by canary percentages, feature flags, and automatic rollback. Security exposure can occur if a new feature inadvertently exposes sensitive data -- mitigate this with security-focused feature flags that are reviewed by the security team before enabling, and with synthetic monitors that specifically test authorization boundaries. The risk of not testing in production is arguably larger: deploying code that passed all staging tests but fails under real conditions, affecting 100% of users with no advance warning.

Testing in Production -- Canary Deployments, Feature Flags, and Synthetic Monitoring | QASkills.sh