top of page

Tutorial 10: Continuous Evaluation in Production

  • Shawn West
  • May 31
  • 3 min read

Updated: Jul 13

The model is live. Now what? Continuous eval = catch regression early, build trust, maintain quality.

Step 1: Online Eval Sampling (10 min)

Don't eval every production request. Sample:

import random

def maybe_eval(request, response):
    if random.random() < 0.01:  # 1% sample
        async_evaluate(request, response)

1% of traffic = enough signal at low cost.

Step 2: Async Eval (10 min)

Don't block the user response. Eval in the background:

def handle_request(request):
    response = call_llm(request)
    
    # Return to user immediately
    send_response(response)
    
    # Eval asynchronously
    if should_sample():
        queue_eval_job({"request": request, "response": response})

Background worker processes the queue.

Step 3: Track Quality Metrics (10 min)

def evaluate_production(sample):
    grades = grade_with_rules_and_judge(sample.response)
    
    record_metric("prod_quality.helpfulness", grades["helpfulness"])
    record_metric("prod_quality.accuracy", grades["accuracy"])
    record_metric("prod_quality.passed", 1 if grades["pass"] else 0)

Surface in dashboards. Quality trend over time.

Step 4: User Feedback Loop (10 min)

In-product feedback:

  • Thumbs up/down on responses

  • "This was helpful" / "This was unhelpful"

  • Specific complaints ("not accurate", "too long")

def on_feedback(message_id, rating, reason=None):
    save_feedback({
        "message_id": message_id,
        "rating": rating,
        "reason": reason,
        "variant": get_variant(message_id),
        "model_version": get_model_version(message_id),
    })

Feedback rate = ground truth. Compare to eval grades; calibrate.

Step 5: Anomaly Detection (10 min)

def detect_anomaly(metric_name):
    recent = get_metric_values(metric_name, last_n=24)  # 24 hours hourly
    historical = get_metric_values(metric_name, last_n=24*7)  # 1 week
    
    if mean(recent) < mean(historical) - 2 * std(historical):
        alert(f"{metric_name} dropped 2 sigma below baseline")

Statistical baseline. Alert on deviation.

Step 6: Cohort Analysis (10 min)

Quality may differ by user type:

def quality_by_cohort():
    by_cohort = defaultdict(list)
    for sample in production_samples:
        cohort = get_user_cohort(sample.user_id)  # new vs. power user, segment, etc.
        by_cohort[cohort].append(sample.quality_score)
    
    for cohort, scores in by_cohort.items():
        print(f"{cohort}: {mean(scores):.2f}")

If quality is worse for new users, the prompt may not be onboarding-friendly.

Step 7: Dashboard (15 min)

Quality dashboard:

  • Pass rate over time (line)

  • Per-category pass rate (heatmap)

  • Top failure categories (bar)

  • User feedback rate (line)

  • Cost per request (line)

  • Latency p50/p99 (line)

Single place. Engineers + product see the same numbers.

Step 8: SLO for Quality (10 min)

Like service SLOs:

quality_slo:
  target: 95%  # of responses pass eval
  measurement_window: 7d
  burn_rate_alert: 2x  # burning budget 2x faster than allowed

Production drops below 90% pass rate for a sustained period = page.

Step 9: Human Review Sampling (10 min)

Random sample for human review:

def daily_review_sample(n=20):
    today = get_today_samples()
    sample = random.sample(today, n)
    # Add edge cases too
    sample.extend(get_today_failures()[:10])
    save_for_review(sample)

Reviewers spot-check. Catches things machines miss.

Step 10: Close the Loop on Production Issues (10 min)

When you detect a quality issue:

  1. Investigate (which cases? which users? what changed?)

  2. Reproduce (replay the failures)

  3. Hypothesize (prompt, model, RAG corpus, etc.)

  4. Fix (test in eval first; A/B test in prod)

  5. Add to eval set (prevent regression)

  6. Post-mortem (what could have caught this sooner?)

Every production issue = improvement to eval coverage.

What You Just Did

Continuous evaluation in production. Sampling, anomaly detection, feedback loop, SLO, human review. Eval is no longer a one-time thing; it's how you operate AI products.

Common Failure Modes

No sampling. Eval everything = cost blow-up.

Sample too small. No signal.

Feedback never analyzed. Collected but unread.

No alerts. Quality drops; nobody notices.

No human review. Metrics look fine; users hate it.

You're Done

You've completed Path 20. Eval sets, automated grading, LLM judges, regression tracking, A/B testing, drift monitoring, CI integration, failure replay, cost control, continuous evaluation in production.

You've now finished 20 paths covering Git, SQL, Docker, Kubernetes, observability, CI/CD, system design, performance, security, AI evals — plus the original paths for testing fundamentals, frontend, backend, AI agents, and more.

Recommend revisiting paths matching your current focus, or applying these techniques in a real project.

Related reading

Keep learning. This article is part of the AI in Quality & Delivery path in the ShiftQuality Learning Center. Use AI in delivery — and evaluate it honestly — without the hype.

bottom of page