AI Agent Error Recovery — When Agents Fail, Hallucinate, or Get Stuck
Master error detection, reflection prompting, alternative tool selection, human-in-the-loop escalation, and graceful degradation for production agents.
webcoderspeed.com
67 articles
Master error detection, reflection prompting, alternative tool selection, human-in-the-loop escalation, and graceful degradation for production agents.
Feature flags for AI: model switching, percentage rollouts, targeting rules, cost kill switches, A/B testing, OpenFeature SDK integration, and per-flag quality metrics.
Ground LLM responses in facts using RAG, self-consistency sampling, and faithful feedback loops to reduce hallucinations and build user trust.
Validate LLM outputs against schemas, business rules, and semantic constraints with automated retry and fallback mechanisms.
Product wants features. Engineering wants to fix the architecture. Neither fully understands the other''s constraints. The result is either all-features-no-quality or all-refactoring-no-shipping. The fix requires building a shared language around trade-offs, not just better processes.
Build durable background job systems resistant to timeouts, poison pills, and duplication. Implement heartbeats, deduplication, and observability patterns.
You''ve been running backups for 18 months. The disk dies. You go to restore. The backup files are empty. Or corrupted. Or the backup job failed silently on month 4 and you''ve been running without a backup ever since. Untested backups are not backups.
You add ON DELETE CASCADE to a foreign key. You delete a test organization. It cascades to users, which cascades to sessions, orders, invoices, activity_logs — 10,000 rows gone in milliseconds. No warning, no undo. Cascade deletes are powerful and dangerous.
You added a circuit breaker to protect against cascading failures. But it never opens — requests keep failing, the downstream service stays overloaded, and your system doesn''t recover. Here''s why circuit breakers fail silently and how to configure them correctly.
The startup was running fine at $3,000/month AWS. Then a feature launched, traffic grew, and the bill hit $47,000 before anyone noticed. No alerts. No budgets. No tagging. Just a credit card statement and a very uncomfortable board meeting.
"It works on staging" is one of the most dangerous phrases in software. The timeout is 5 seconds in dev, 30 seconds in prod. The cache TTL is different. The database pool size is different. The feature flag is on in staging but off in prod. Config drift makes every deployment a gamble.
You scale your app to 3 instances. Your daily billing cron runs on all 3 simultaneously. 3x the emails, 3x the charges, 3x the chaos. Distributed cron requires distributed locking. Here''s how to ensure your scheduled jobs run exactly once across any number of instances.
Your DLQ has 2 million messages. They''ve been there for 3 months. Nobody noticed. Those are failed orders, unpaid invoices, and unprocessed refunds — silently rotting. Here''s how to build a DLQ strategy that''s actually monitored, alerting, and self-healing.
The email job has been failing silently for three months. 50,000 emails not sent. Or the background sync has been silently skipping records. Or the backup has been succeeding at creation but failing at upload. Silent failures are the most dangerous kind.
You deploy to all instances simultaneously. A bug affects 5% of requests. Before you can react, 100% of users are hitting it. Canary deployments let you catch that bug when it''s hitting 1% of traffic, not 100%.
Your system handles 1,000 users today. You''re designing for 10,000. Not 10 million — 10,000. Most "design for scale" advice is written for companies you''re not. What actually changes at 10x, and what''s over-engineering that will hurt more than help?
Your message queue delivers an event twice. Your consumer processes it twice. The order ships twice, the email sends twice, the payment charges twice. At-least-once delivery is a guarantee — not a bug. Here''s how to build idempotent consumers that handle duplicate events safely.
What makes execution durable, Temporal workflows vs activities, automatic retry, long-running workflows, saga pattern, signals and queries, and comparison to BullMQ and Inngest.
"We need to pay down tech debt" means nothing to a product manager or CFO. But "every new feature takes 3x longer than it should because of architectural decisions made 2 years ago, and here''s the $200k annual cost" is a budget conversation they understand.
You have 200 feature flags. Nobody knows which ones are still active. Half of them are checking flags that were permanently enabled 18 months ago. The code is full of if/else branches for features that are live for everyone. Flags nobody owns, nobody turns off, and nobody dares delete.
"The app is slow. Fix it." — said by the founder, with no further context. Is the homepage slow? Checkout? API responses? For which users? On mobile? Under what conditions? Turning vague business pressure into actionable performance work requires measurement before code.
The incident was bad. Someone deployed bad code. Someone missed the alert. Someone made a wrong call at 2 AM. A blame postmortem finds the guilty person. A blameless postmortem finds the system conditions that made the failure possible — and actually prevents the next one.
The alert fires. You''re the most senior engineer available. The site is down. Users are affected. Your team is waiting for direction. What do you actually do in the first 10 minutes — and what does good incident command look like vs. what most teams actually do?
Design Kubernetes health checks, dependency health aggregation, and graceful degradation. Learn when to check dependencies and avoid cascading failures.
You hired a senior engineer who looked great on paper. Six months later, they''ve shipped nothing, dragged down two junior engineers, and the team is demoralized. A bad senior hire costs 10x what a bad junior hire costs. The fix is in what you test for, not just what you look at.
Learn idempotency key design, idempotency stores with TTL, request fingerprinting, and CQRS deduplication patterns for safe retries.
Network timeout on a payment request. Client retries. Customer gets charged twice. This is the most expensive bug in fintech — and it''s completely preventable with idempotency keys. Here''s the complete implementation.
Idempotent AI: idempotency keys for retries, Redis caching, replay on retry, avoiding duplicate tool calls, database upserts, and webhook deduplication.
Master consumer groups, offset management, exactly-once semantics, dead-letter queues, and consumer lag monitoring for production Kafka.
Six months in. $800k spent. The project isn''t working. Sunk cost bias says keep going. The business case for stopping is clear. Making the engineering argument to kill a project — and knowing when you''re right — is one of the hardest senior skills.
The senior engineer proposes Kafka for the notification system. You have 500 users. The junior engineer proposes a direct function call. The senior engineer is technically correct and strategically wrong. Knowing when good architecture is overkill is the skill that separates senior from staff.
Your service elects a leader to run background jobs. The network hiccups for 5 seconds. The old leader thinks it''s still leader. The new leader also thinks it''s leader. Both start processing the same queue. Now you have duplicate work, corrupted state, and a split-brain.
Build resilient LLM systems with multi-provider failover chains, circuit breakers, and cost-based routing using LiteLLM to survive provider outages.
Audit logs are critical for compliance and debugging. But an audit_logs table that grows without bounds will fill your disk, slow every query that touches it, and eventually crash your database. Here''s how to keep your logs without letting them kill production.
Your logs are full. Gigabytes per hour. Health check pings, SQL query text, Redis GET/SET for every cached value. When a real error occurs, it''s buried under 50,000 noise lines. You log everything and still can''t find what you need in a production incident.
Your feature needs an API from the Platform team, a schema change from the Data team, and a design component from the Design System team. All three teams have their own priorities. Your deadline is in 6 weeks. How you manage this will determine whether you ship.
Mid-level engineers are technically strong but often miss the senior behaviors: anticipating downstream impact, communicating trade-offs, owning outcomes beyond their code. Effective mentoring targets the specific gaps, not general advice to "think bigger."
You deploy a migration that runs ALTER TABLE on a 40-million row table. PostgreSQL rewrites the entire table. Your app is stuck waiting for the lock. Users see 503s for 8 minutes. Schema changes on large tables require a completely different approach.
Your webhook processor receives 10,000 events/second. Your database can handle 500 inserts/second. Without backpressure, your queue grows unbounded, memory fills up, the process crashes, and you lose all the unprocessed events in memory.
Something is wrong in production. Response times spiked. Users are complaining. You SSH into a server and grep logs. You have no metrics, no traces, no dashboards. You''re debugging a distributed system with no instruments — and you will be for hours.
A user sends 10,000 requests per minute to your API. No rate limiting. Your server CPU spikes to 100%. Your database runs out of connections. Every other user sees 503s. One script can take down your entire service — and it happens more often than you think.
Error rate spikes after deploy. You need to roll back. But the migration already ran, the old binary can''t read the new schema, and "reverting the deploy" means a data loss decision. Rollback is only possible if you design for it before you deploy.
Implement bulletproof shutdown. Handle SIGTERM/SIGINT, drain database connections, stop consuming messages, align with K8s termination periods, and test shutdown reliability.
Three engineers. Twelve alerts last night. The same flapping Redis connection alert that''s fired 200 times this month. Nobody sleeps through the night anymore. On-call burnout isn''t about weak engineers — it''s about alert noise, toil, and a system that generates more incidents than the team can fix.
Eliminate dual-write problems with the outbox pattern. Learn polling publishers, CDC with Debezium, and building reliable event-driven systems.
A junior engineer with access to production and insufficient guardrails runs a database migration directly on prod. Or force-pushes to main. Or deletes an S3 bucket thinking it was the staging one. The fix isn''t surveillance — it''s systems that make the catastrophic mistake require extra steps.
Your RDS instance is db.r6g.4xlarge and CPU never exceeds 15%. Your ECS service runs 20 tasks but handles traffic that 4 could manage. You''re paying for comfort headroom you never use. Right-sizing recovers real money — without touching application code.
In distributed systems, failure is never all-or-nothing. A service returns a response — but it''s corrupt. An API call times out — but the action already executed. A message is delivered — but the reply never arrives. This is partial failure, and it is the hardest problem in distributed systems.
Stripe times out at 30 seconds. Did the charge happen? You don''t know. You charge again and double-charge the customer. Or you don''t charge and ship for free. Payment idempotency and webhook reconciliation are the only reliable path through this.
TechCrunch publishes your launch article at 9 AM. Traffic hits 50x normal. The servers that handled your beta just fine fail under the real launch. You''ve never tested what happens above 5x. The outage is the first piece of coverage that goes viral.
User saves their profile. Page reloads. Shows old data. They save again — same thing. The write went to the primary. The read came from the replica. The replica is 2 seconds behind. Read-after-write consistency is the hardest problem with read replicas.
The codebase is a mess. Nobody wants to touch it. The "obvious fix" requires changing 40 files. Every change breaks three things. Refactoring legacy code safely requires the strangler fig pattern, comprehensive tests before changing anything, and very small steps.
The disk dies at 2 AM. You have backups. But the restore takes 9 hours because nobody tested it, the database is 800GB, the download from S3 is throttled, and pg_restore runs single-threaded by default. You could have restored in 45 minutes with the right setup.
Your service is degraded, returning errors 30% of the time. Smart clients with retry logic start hammering it — 3 retries each means 3x the load on an already failing system. The retry storm amplifies the original failure until full collapse. Here''s how to retry safely.
The codebase is painful. The team wants to rewrite it. The CTO wants to maintain velocity. Both are right. The rewrite vs refactor decision is one of the highest-stakes calls in software — get it wrong and you lose two years of productivity or two more years of compounding debt.
The CTO wants to rewrite everything in Rust. The PM wants to skip testing to ship faster. The founder wants to store passwords in plain text "for now." Saying no effectively requires more than being technically right — it requires translating risk into business language.
Traffic spikes 10x at 8 AM on Black Friday. Auto-scaling triggers but takes 4 minutes to add instances. The database connection pool is exhausted at minute 2. The checkout flow is down for your highest-traffic day of the year.
You rename a column. The new service version uses the new name. The old version, still running during the rolling deploy, tries to use the old name. Database error. The migration that passed all your tests breaks production because both old and new code run simultaneously during deployment.
The database has a replica. The app has multiple pods. You think you''re resilient. Then the single Redis instance goes down, and every service that depended on it — auth, sessions, rate limiting, caching — stops working simultaneously. SPOFs hide in plain sight.
Define meaningful SLOs and SLIs that align product and engineering. Implement error budgets to enable fast iteration without breaking production.
Network partition splits your 3-node cluster into two halves. Both halves think they''re the primary. Both accept writes. Network heals. You have two diverged databases with conflicting data. This is split brain — one of the most dangerous failure modes in distributed systems.
Every operation is a synchronous HTTP call. User signup calls email service, which calls template service, which calls asset service. Any service down means signup is down. Any service slow means signup is slow. Synchronous coupling is the enemy of resilience.
Twilio has an outage. Every user trying to log in can''t receive their OTP. Your entire auth flow is blocked by a third-party service you don''t control. Fallbacks, secondary providers, and graceful degradation are the only way to maintain availability.
Sessions table. Events table. Audit log. Each row is small. But with 100,000 active users writing events every minute, it''s 5 million rows per day. No one added a purge job. Six months later the disk is full and the database crashes.
The t3.micro database that "works fine in staging" OOMs under real load. The single-AZ deployment that''s been fine for two years fails the week of your biggest launch. Underprovisioning is the other edge of the cost/reliability tradeoff — and it has a much higher price.
Build reliable webhook systems with HMAC-SHA256 signatures, idempotency keys, exponential backoff, dead-letter queues, and production testing patterns.
Master zero-downtime deployments with rolling updates, graceful shutdown, health checks, and blue/green strategies. Learn SIGTERM handling and preStop hooks.