Lesson 27 / 31
Common Pitfalls in Production
Recognise the mistakes that make LLM traces missing, misleading or risky, and how to avoid each.
By Rahul Agarwal · 15 years in web development
Mistakes teams repeat
A short list of problems seen again and again. Lost traces: no flush in serverless or scripts, or tracing disabled by a missing environment variable in production. Broken trees: work started in a new thread, task queue or another service loses the trace context, so spans appear as separate traces; propagate context (OpenTelemetry headers or passing the trace ID) explicitly. No version info: traces lack prompt version, model or release, so regressions cannot be pinned. Secrets and personal data in payloads because whole request objects were logged. Noise: every helper decorated, so traces are thousands of spans deep. Mixed environments: dev and prod in one project, corrupting metrics. Unvalidated judges whose scores drive decisions. Ignoring cost of observability: tracing large payloads such as full documents or images at 100%. Most are fixed by a short checklist reviewed whenever a new LLM feature ships.
Propagate context across async boundaries
Python context variables are copied into new asyncio tasks (and asyncio.to_thread), but not into threads started with ThreadPoolExecutor.submit or loop.run_in_executor, and never into a Celery job or another process. Pass the trace ID along and re-attach it, or use OpenTelemetry propagation, so background work joins the right trace.
A pre-launch checklist as config
A team checklist kept in the repository so every new LLM feature is reviewed the same way.
llm_observability_checklist:
tracing_enabled_in_prod: true
flush_on_shutdown: true # serverless, cron, CLI
separate_project_per_env: true
trace_attributes: [user_id, session_id, release, prompt_version]
masking_function: enabled
retention_days: 30
sampling:
default_rate: 0.2
always_keep: [errors, negative_feedback]
online_evaluators: [faithfulness, policy_check]
alerts: [p95_latency, daily_cost, feedback_drop]Quick check: Spans from a background worker show up as separate traces instead of under the original request. What is the likely cause?
- Trace context was not propagated to the worker
- The model returned too many tokens
- The project has too many tags
- The masking function removed the spans
Answer
Trace context was not propagated to the worker — Spans attach to whatever trace context is current. In a separate worker or service that context is absent unless you pass and re-attach it.