Production Problems in AI-Built Apps
How to automatically catch common production problems in AI-built apps using monitoring, tracing, static analysis, and CI gates.
Title options: "Production Problems in AI-Built Apps: How to Catch Them Automatically", "Production Risks in AI-Built Apps", "How to Catch AI Code Problems Without Manual Review"
A developer reads code and finds problems.
The more realistic future looks like this:
The system continuously checks. Deployment is blocked automatically. Runtime patterns are detected. An AI reviewer skill catches repeated mistakes.
Can you find these problems without code review?
Yes. But to reduce human eyeball review, you need automated guardrails.
Most problems in AI-built apps follow patterns.
Slow APIs Rising DB query counts Repeated SQL Large reads without pagination Timeouts from long AI work Endpoints that get dramatically slower as users grow Exploding token costs Rising background job failures Unauthorized access attempts
You can catch most of these with monitoring, tracing, static analysis, performance tests, and CI gates — without reading every line of code.
The point is not "skip review." The point is make review systematic instead of relying on human memory.
1. In production, look for symptoms
The four basic signals to watch are:
latency: how slow is it? traffic: how often is it called? errors: how often does it fail? saturation: how full are CPU, memory, DB connections, and queues?
These are the golden signals from SRE. Latency increases are often an early sign of saturation, and tail latency like p99 reveals problems that average response time hides. (Google SRE)
For AI apps, add a few more:
AI token usage AI API call count AI API timeouts Job queue wait time Job failure rate Retry count Cost per user File processing time DB query count DB total time
In other words, do not just ask, "Is the server alive?" Ask, "How much work did one request do internally?"
2. Use tracing to find N+1 queries and repeated calls
Distributed tracing is one of the most powerful tools.
If tracing a single request looks like this, it is dangerous:
GET /users DB: SELECT * FROM users DB: SELECT * FROM orders WHERE user_id = 1 DB: SELECT * FROM orders WHERE user_id = 2 DB: SELECT * FROM orders WHERE user_id = 3 DB: SELECT * FROM orders WHERE user_id = 4 ... DB: SELECT * FROM orders WHERE user_id = 100
This is the classic N+1 query.
A developer does not need to read the code to see it. The trace is enough.
One request makes 100+ DB queries The same SQL repeats with only the parameter changing Endpoint latency grows with the number of records
OpenTelemetry provides a standard way to collect and export traces, metrics, and logs. DB client spans let you observe DB call duration, so you can trace how many DB calls happen inside one endpoint and where they slow down. (OpenTelemetry)
Good automatic detection rules look like this:
Warning if one HTTP request makes more than 20 DB queries Alert if it makes more than 50 Suspect N+1 if the same SQL pattern repeats 10+ times Suspect DB bottleneck if DB time is >70% of total request time
3. Do not just watch slow APIs — watch how they get slower
"Alert if response time exceeds 2 seconds" is not enough.
Structural problems in AI apps usually show up like this:
50 records: 100ms 500 records: 800ms 5,000 records: timeout
What matters is not just current speed but the slope as data grows.
Watch these metrics:
p50 latency p95 latency p99 latency response size rows returned DB query count DB total duration memory usage CPU usage
For example, if GET /documents starts at 200ms but p95 keeps rising as document count grows, suspect pagination, indexing, or query structure.
4. Catch full scans with slow query logs and query plans
The database can tell you about dangerous queries even without code review.
Watch for:
slow query log query duration rows scanned rows returned index usage sequential scans temporary sorts
PostgreSQL lets you inspect query plans with EXPLAIN to see how the planner executes a query. Because the planner chooses a plan based on query structure and data properties, frequently used queries deserve a plan check. (PostgreSQL)
For example, this signal is dangerous:
Seq Scan on documents Rows Removed by Filter: 499980 Execution Time: 3500ms
The meaning is simple:
Only a few rows are needed but the DB is scanning most of the table
Usually this means no index exists or the query cannot use one.
You can automate this too:
Run EXPLAIN on critical queries before deploy Fail if Seq Scan appears on a table above a certain size Warn if estimated rows differ greatly from actual rows Fail if query time exceeds the budget
5. Missing pagination is easy to catch at runtime
APIs without pagination are visible in operational metrics.
Look for these patterns:
response_bytes keeps growing rows_returned rises to thousands or tens of thousands p95 latency grows with data count memory usage spikes per request browser freezes on list screens
Automatic rules can be:
Warning if rows_returned > 200 in a list API Alert if rows_returned > 1000 Warning if response size > 1MB Warning if a list endpoint is called without pagination parameters
Also bake rules into the API contract itself:
Every list API has a limit Default limit is 20 or 50 Maximum limit is 100 or 200 Return a cursor or page token
6. Long AI work shows up as HTTP latency and timeouts
This is extremely common in AI apps.
User request → Parse PDF → Call AI → Generate summary → Save to DB → Send email → HTTP response
This structure is fine for a demo but dangerous in production.
In production, you will see:
POST /analyze p95 latency over 30 seconds Rising HTTP timeouts Users pressing the same button multiple times Rising AI API retries Duplicate saved job results Server memory spikes
Automatic rules:
Warning if an HTTP request takes longer than 5 seconds Any endpoint over 10 seconds that calls an AI API is a candidate for background job conversion File processing + AI call + email in one request is a blocker
A better structure:
HTTP request only creates a job Immediately return a job_id Worker processes in the background User polls job status
Operational metrics should be job-centered, not API-centered:
job_queue_wait_time job_processing_time job_success_rate job_failure_rate job_retry_count job_cancel_count ai_token_usage_per_job ai_cost_per_job
7. Catch authorization issues with automated security tests
Authorization bugs are often easier to catch with negative tests than with code review.
Imagine a documents API:
GET /documents/:id PUT /documents/:id DELETE /documents/:id
Automated tests should ask:
Can User B read a document created by User A? Can User B modify User A's document? Can a regular user call an admin API? Can a logged-out user download a file?
These tests can run in CI without a human reviewing every change.
OWASP ASVS provides security requirements and verification criteria for web applications, making it a good source for turning access control, input validation, error handling, and logging into automated test checklists. (OWASP Foundation)
Some authorization issues can also be detected in production monitoring:
Rising 403s More attempts to access another user's resources More failed admin endpoint calls Unusual spikes in download API calls
But if you find authorization issues in production, it is already risky. Block them with automated tests before deploy when possible.
8. Replace code review with static analysis rules
Repeated mistakes can be caught with static analysis.
In a JavaScript/TypeScript app, you might forbid patterns like:
findMany() without take getAllUsers() getAllDocuments() SELECT * await db.* inside a for loop db query inside map(async ...) API route without auth middleware list endpoint without pagination external API call without timeout
Tools include CodeQL, Semgrep, and ESLint custom rules. CodeQL treats code like data to find vulnerabilities and error patterns, and integrates with GitHub code scanning alerts. (GitHub Docs) Semgrep finds security issues and specific code patterns in first-party code and integrates into CI/CD. (docs.semgrep.dev)
For example, you can create this rule:
Rule: Prisma findMany must include take. Bad code: db.user.findMany() Allowed code: db.user.findMany({ take: 50, cursor: ... })
Another rule:
Rule: An API route fails if it does not include currentUser or requireAuth. Bad code: export async function GET(req) { const docs = await db.document.findMany() return Response.json(docs) } Allowed code: export async function GET(req) { const currentUser = await requireAuth(req) const docs = await db.document.findMany({ where: { userId: currentUser.id }, take: 50 }) return Response.json(docs) }
These rules are more consistent than human review.
9. Turn performance tests into CI gates
If you first discover a performance problem in production, it is too late. Run at least a small load test before deploy.
For example, seed staging with large test data:
users: 100,000 documents: 1,000,000 messages: 5,000,000 jobs: 500,000
Then set budgets for critical APIs:
GET /documents p95 < 500ms GET /documents DB query count <= 5 GET /documents rows_returned <= 100 POST /ai-jobs response time < 1s GET /jobs/:id p95 < 300ms
Load testing tools like k6 let you define thresholds so performance expectations become pass/fail criteria in CI, not guesses. (Grafana Labs)
Do not only test "lots of traffic." For AI apps, also test:
Large file uploads Long prompts Concurrent AI job creation AI API failures AI API timeouts Duplicate submits Job retries Per-user rate limits
10. Catch AI cost explosions with usage monitoring
In AI apps, cost matters as much as performance.
Watch these metrics in production:
AI calls per user_id AI calls per endpoint input tokens per job output tokens per job cost per model extra cost from retries cache hit rate duplicate document reprocessing count
Dangerous patterns:
One user calls hundreds of times in a short window Same document keeps being summarized Failed AI requests keep retrying Free-tier users use expensive models List screens call an AI API per row
Automatic defenses:
Daily token limit per user Max token limit per job Budget per model Hash-based cache for duplicate documents Max retry count Route expensive work through a queue Show cost on admin dashboard
11. Build a "Production Guardrail Skill" during development
The best approach is to have a separate AI skill automatically check the app after AI writes the code.
This skill should not write impressionistic code review essays. It should apply deployment-blocking criteria.
For example, add a file like this to the project:
.ai/skills/production-guardrail.md
With content like:
You are a Production Guardrail Reviewer. Goal: Find dangerous structures before deploying an AI-built app to production. Required checks: 1. List API without pagination 2. DB query inside a loop 3. External API call inside a loop 4. findMany without take 5. getAllUsers, getAllDocuments, or similar full reads 6. API without server-side authorization 7. Missing user_id or organization_id ownership check 8. Missing input validation 9. Long AI work inside an HTTP request 10. External API call without timeout 11. Retry without idempotency 12. Missing index in DB migration 13. Background work without a job table/status 14. AI call without token or cost limit 15. Critical path without logging Output format: - Blocker: must fix before deploy - Warning: should fix before deploy - Suggestion: structural improvement For each item include: Problem: Why it is dangerous: Scale at which it breaks: Detectability: Fix direction:
This skill lets the team enforce the same checklist every time, even without a human reviewer.
12. Build a pre-deploy gate
A practical pipeline looks like this:
1. Lint 2. Type check 3. Unit test 4. API contract test 5. Security static scan 6. Custom production rule scan 7. DB migration/index check 8. Large seed data performance test 9. AI usage budget test 10. Production Guardrail Skill review
Deployment criteria must be explicit:
Any Blocker fails deploy p95 latency budget exceeded fails deploy Any list API without pagination fails deploy Any protected API without auth fails deploy DB query count budget exceeded fails deploy AI token budget exceeded fails deploy
With this, common dangerous mistakes are blocked automatically without requiring a human to review every diff.
Automatic detection rule examples
| Problem | Pre-deploy detection | Runtime detection | Response |
|---|---|---|---|
| Full array scan | Static rule detects getAll*, repeated .filter() | CPU rises, latency scales with data count | Use Map, index, or DB query |
| N+1 query | Detect DB call inside loop | DB spans surge per request | Use join, batch query, or eager loading |
| Missing pagination | Detect findMany without take | rows_returned and response_bytes grow | Apply limit and cursor |
| Missing index | Migration/index check, EXPLAIN | Slow query, Seq Scan, rising DB time | Add index or rewrite query |
| Long AI request | Detect AI/PDF processing in API route | HTTP timeout, rising p95/p99 | Move to job queue |
| Missing authorization | Protected route auth test | Unusual 403/404 patterns | Add server-side authorization |
| Missing validation | Schema validation test | Rising 500s, invalid inputs | Add backend validation with Zod/Pydantic |
| Duplicate retry | Detect missing idempotency key | Duplicate emails/payments/jobs | Add idempotency by request_id/job_id |
| AI cost spike | Token budget test | Per-user cost/token spike | Rate limit, cache, budget |
| Insufficient logging | Critical path logging check | Cannot trace cause during incident | Log request_id, user_id, job_id |
Dashboards that matter
For AI apps, split dashboards like this:
API dashboard
p50 / p95 / p99 latency per endpoint error rate per endpoint request count per endpoint response size per endpoint timeout count per endpoint
DB dashboard
top 20 slow queries query count per request DB total duration per request rows scanned / rows returned index scan vs sequential scan connection pool usage
AI dashboard
calls per model input/output tokens per model cost per model AI cost per endpoint AI cost per user retry count timeout count cache hit rate
Job dashboard
queue length queue wait time job processing time job success/failure rate retry count stuck jobs dead letter queue
Security dashboard
401 / 403 rate admin API access attempts cross-user resource access failures download success/failure ratio user_ids with unusually high request volume
Frequently asked questions
What is a production guardrail?
A production guardrail is an automated check or monitor that catches risky code, slow queries, security gaps, or failing jobs before or soon after they reach real users.
What should I monitor in a web application?
Monitor response time, error rate, database query count and duration, queue depth, AI token cost, and unusual access patterns. Start with the metrics that affect users first.
What is the difference between logging and tracing?
Logs record discrete events. Tracing follows a single request across multiple services so you can see where time is spent and where failures happen.
What is a CI gate?
A CI gate is an automated check that runs before code can be deployed, such as lint, tests, type checking, security scans, or query plan checks.
How do I stop the same production bug from repeating?
Turn the incident into a rule: add a static analysis check, a test, or an alert that would catch the same pattern next time. Then include it in your CI pipeline.
The point: detect after and block before
Monitoring helps you find problems fast. But by then, users may already be affected.
So the structure should be:
During development: AI skill + static analysis + lint rules Before deploy: CI gates + performance tests + security tests + DB query plan checks In production: observability + dashboards + alerts + anomaly detection After an incident: Turn the discovered issue into a static rule or test
The last step is critical.
Any problem found in production should not be left to human memory. It must become a rule.
Incident occurs → Root cause analysis → Extract detectable pattern → Add static rule or runtime alert → Include in CI gate → Prevent the same mistake again
The takeaway
Developers are moving away from reading every line of code. In an environment where AI writes much of the code, expecting a human to review every diff does not scale.
What is needed instead is automated production guardrails.
Find dangerous patterns in code Validate performance and security before deploy Monitor latency, query count, token cost, job failure in production Turn every discovered issue into a rule so it does not repeat
Problems in AI-built apps rarely appear out of nowhere. They send signals first.
Response time slowly increases DB query count rises Same SQL repeats Response size grows Job queue backs up AI cost spikes on a specific endpoint A specific user's failure rate rises
If you can see these signals, you can find many problems without traditional code review.
And the better approach is to block them before they reach production.
In the AI era, production development rewards the ability to build systems that catch mistakes automatically even more than the ability to read code perfectly.
About the Author

Jaehee Song
Enterprise data platform architect with 20+ years of experience building data systems for Fortune 500 companies. AI development educator who has taught vibe coding and AI development to hundreds of students. Founder of Seattle Partners, helping Korean technology startups navigate the US market.