The problem: scale, noise, and 3 AM alerts

Running a classifieds marketplace at OLX India’s scale means roughly 150 microservices, tens of billions of log lines flowing through a centralized ClickHouse cluster, and a user base spanning the country. Ad listings, buyer-seller chat, payments, content moderation, search, and notifications are all wired together through an event-driven backbone — and when something breaks in that web of dependencies, incidents don’t wait for business hours.

Before automation, figuring out what broke and why looked like this every time:

  1. An on-call engineer gets paged by PagerDuty at 3 AM.
  2. They pivot between New Relic dashboards, ClickHouse log queries, and Slack threads.
  3. 30–60 minutes go by just understanding the blast radius — before a single line of mitigation gets written.

That investigation time was a silent tax on our MTTR (Mean Time to Resolution), and it was eating into engineers’ sleep and focus. So we asked: can we automate the “what happened and why” part of incident response?

We now believe the answer is yes — but we got there in two attempts, not one.

Round one: IntelliOps, our in-house attempt

“The best way to appreciate a managed service is to build the unmanaged version yourself first.”

Before AWS DevOps Agent existed in our toolbox, we built IntelliOps: an internal AI-powered RCA assistant, fully self-hosted.

The stack:

  • UI: LibreChat, an open-source chat interface
  • Model: AWS Bedrock running gpt-oss-120b, billed per token
  • Storage: MongoDB, for chat history and token accounting
  • Data sources: ClickHouse MCP (logs), New Relic MCP (APM metrics and traces), Kubernetes MCP (cluster state) — the same three we still use today.
  • Trigger: A Slack listener watching for alert messages matching Incident #<ID>: in the title. On a match, it extracted the incident ID and service name and kicked off an investigation automatically.

It worked, and for a while it was genuinely useful — structured RCA responses appeared in the channel shortly after an alert fired, built from real log and metrics data. But running our own model at scale surfaced real problems:

  • Model cost was ours to own. A complex, multi-service incident — exactly the kind that needs AI assistance most — burns through a lot of tokens across multiple investigation turns. Costs were manageable but unpredictable, scaling directly with incident volume.
  • Context deadline exceeded — the silent-truncation problem. On cascading, multi-service incidents, gpt-oss-120b would hit its context window limit. Output came back truncated, often with no clear signal that the analysis was incomplete. Half an RCA that looks like a whole one is arguably worse than no RCA.
  • Full maintenance burden. LibreChat upgrades, MongoDB operations, MCP server deployments, Bedrock credential rotation — every component was one more thing that could break at 3 AM.
  • A single, fragile trigger path. IntelliOps only investigated incidents posted to one specific Slack channel, in one specific message format. If Slack was slow or the format drifted, nothing fired.
  • No de-duplication. One infrastructure event cascading into ten downstream alerts meant ten separate analyses flooding the channel.
  • No AWS infrastructure visibility. IntelliOps could reason about logs, APM data, and Kubernetes state — but not about the AWS resources underneath them. Giving it visibility into EC2, RDS, ElastiCache, OpenSearch, and the rest would have meant hand-building and maintaining a separate MCP server per AWS service, which we never got to.

IntelliOps Architecture:

IntelliOps wasn’t a failed project — it was a proof of concept that validated the whole approach. It just made clear that the orchestration layer needed to be somebody else’s problem.

Round two: AWS DevOps Agent

AWS DevOps Agent is a fully managed AI agent for engineering operations. It connects to your observability stack, listens for signals, and autonomously investigates incidents — querying metrics, scanning logs, correlating traces, and generating structured RCA reports with mitigation recommendations. Think of it as a Level 2 on-call engineer who never sleeps and already knows every tool in the stack.

We didn’t evaluate it in the abstract — we evaluated it against every pain point IntelliOps had already taught us:

  • Native AWS integration. Our infrastructure already lives in AWS. A read-only IAM role gives the agent visibility into the account topology — EC2, RDS, ElastiCache, OpenSearch, and more — without us building a single extra MCP server.
  • Native Kubernetes access, the same way. Rather than a separate kubeconfig or credential to manage, we granted the agent’s IAM role read-only cluster access through an EKS access entry — the same IAM-first pattern as the AWS account access above, mapped straight to a read-only Kubernetes RBAC policy.
  • The same MCP layer, reused. ClickHouse and New Relic MCP servers we’d already built for IntelliOps plugged straight in as data sources. Nothing was thrown away.
  • Direct, webhook-driven triggering. No Slack-parsing middleman — PagerDuty posts straight to the agent’s webhook.
  • Slack-native output for triggered incidents, plus a UI for everything else. Automated investigations land in Slack, where the team already works during incidents — but engineers can also open the DevOps Agent UI directly for day-to-day investigation: ad hoc questions, exploratory debugging, or anything that isn’t a live page.
  • A persistent incident knowledge base, not a one-off chat session — past investigations inform future ones, whether they were triggered from PagerDuty or ad-hoc investigations from users via UI.
  • One unified RCA skill file, so every investigation follows the same evidence-gathering method regardless of who (or what) triggered it.
  • Built-in de-duplication, grouping cascading alerts into a single “LINKED” investigation instead of spamming the channel.
  • Fully managed. No LibreChat, no MongoDB, no Bedrock credential rotation, no per-token cost to plan around.

AWS DevOps Agent architecture:

IntelliOps vs. AWS DevOps Agent

DimensionIntelliOps (in-house)AWS DevOps Agent
UILibreChat (self-hosted)Slack for automated output, plus a dedicated DevOps Agent UI for day-to-day, on-demand investigation
Modelgpt-oss-120b on Bedrock — billed per tokenManaged — no model to select, host, or pay for directly
StorageMongoDB (self-managed)Managed
TriggerSlack listener parsing an Incident #<ID>: patternDirect PagerDuty Incident Workflow webhook, or an engineer querying the UI directly
Observability data sourcesClickHouse + New Relic + Kubernetes (self-built MCP servers)Same three MCP servers, reused as-is
Kubernetes accessKubernetes MCP server, credentialed separatelySame Kubernetes MCP, authorized via an EKS access entry mapped to the agent’s IAM role — read-only, no separate kubeconfig
AWS infrastructure visibilityWould need a hand-built MCP server per AWS service (EC2, RDS, ElastiCache, OpenSearch, …) — never fully builtNative read-only IAM role sees the full AWS account topology out of the box
Incident memoryNone beyond a raw MongoDB chat logPersistent incident knowledge base, reused across future investigations
Investigation methodAd hoc, per sessionOne unified RCA skill file — same method every time
De-duplicationNone — cascading alerts trigger repeat analysesBuilt-in (LINKED investigations — roughly a quarter of investigations de-duplicated in a recent month)
MaintenanceFully self-managed (LibreChat, MongoDB, MCP servers, Bedrock credentials)Fully managed

The data-source row is identical on purpose — the MCP layer built for IntelliOps carried over directly. This was an orchestration swap, not a data migration.

How the pieces connect

Two ways in. For live incidents, PagerDuty is the automated trigger — Incident Workflows let us define automation that fires across all ~150 services from a single rule, no per-service webhook to maintain. We initially also wired New Relic as a second trigger path, but its default Kubernetes alerting policy generated continuous noise (default critical CPU and memory alerts) that flooded Slack with repetitive de-duplicated investigations. We disabled it as a trigger and kept it purely as a data source. Outside of live incidents, engineers can also open the DevOps Agent UI directly and ask it to investigate something — a suspicious metric, a one-off error spike, anything that doesn’t warrant a page. Same agent, same data sources, same skill file — just a different entry point for day-to-day debugging rather than 3 AM firefighting.

Data gathering. Once triggered — by PagerDuty or a person — the agent fans out in parallel:

  • New Relic MCP — APM metrics, error rates, latency percentiles, distributed traces, and Kubernetes infrastructure samples (HPA/PDB state).
  • ClickHouse MCP — full-text and structured search over centralized application logs, filtered to ERROR/FATAL severity within the incident window.
  • Kubernetes (read-only) — deployments, pods, ReplicaSets, HPA, PDB, rollout history, and cluster events. Access is granted through an EKS access entry that maps the agent’s IAM role to a read-only Kubernetes RBAC policy — no separate kubeconfig or long-lived credential to rotate.
  • Native AWS access (IAM read-only) — the account topology itself, without a dedicated MCP server per service.

Correlation. Trace IDs from New Relic are matched against ClickHouse log entries; pod events are cross-referenced against the incident timeline; the result is synthesized into a report with a root cause, a confidence level, and remediation suggestions — no auto-apply. Automated investigations post the report to Slack; UI-initiated ones stay in the conversation — either way, findings are saved to the shared incident knowledge base.

A simplified example of the kind of log query the agent runs during an investigation:

-- Illustrative pattern, not the production schema
SELECT timestamp, severity, message, trace_id
FROM logs_db.application_logs_dist
WHERE service_name = 'chat-service'
  AND severity IN ('ERROR', 'FATAL')
  AND timestamp BETWEEN :window_start AND :window_end
ORDER BY timestamp DESC
LIMIT 500

And the webhook payload shape PagerDuty sends to trigger an investigation:

{
  "eventType": "incident",
  "incidentId": "INC-7F3K2Q",
  "action": "triggered",
  "priority": "CRITICAL",
  "title": "<incident title>",
  "timestamp": "2026-08-07T02:15:00Z",
  "service": "chat-service"
}

Note: Two schema quirks are worth flagging if you’re building this yourself: priority must be uppercase (CRITICAL, HIGH, MEDIUM, LOW, MINIMAL) even though PagerDuty’s native urgency values are lowercase, and the field is required — a payload missing it gets acknowledged (HTTP 200) but silently triggers nothing.

A real incident, walked through

Scenario: Error rate spike on a production chat service.

TimeWhat happens
T+0:00New Relic alert fires: error rate > 1% for 5 minutes
T+0:00PagerDuty incident created (CRITICAL), Incident Workflow fires
T+0:00Webhook POSTed to AWS DevOps Agent
T+0:01Agent queries New Relic for APM metrics, error traces, throughput
T+0:01Agent queries ClickHouse for ERROR/FATAL logs in the incident window
T+0:01Agent checks Kubernetes: pod restarts, ReplicaSet events, HPA state
T+0:02Trace IDs from New Relic matched against ClickHouse log entries; pod events cross-referenced with the error timeline
T+0:03Root cause identified (e.g., an upstream consumer lag causing a message-processing backlog), with a confidence level
T+0:03Mitigation plan drafted and RCA posted to Slack
T+0:04On-call engineer reads a structured report and starts mitigation

Alert to actionable RCA: roughly 3–5 minutes. Previously: 30–45 minutes of manual investigation.

Results

MetricBeforeAfter
Alert-to-RCA time30–45 min3–5 min
On-call investigation effortHigh — manual pivoting across toolsLow — review an AI-generated report
Incidents requiring manual log divingNearly allSignificantly reduced
CoveragePer-service setup neededAll services, via one PagerDuty workflow

Beyond the numbers: Engineers get a starting hypothesis instead of a blank canvas, every investigation follows the same methodology regardless of who’s on call, and RCA reports build a searchable incident history new team members can learn from. We’re still collecting a full quarter of production data before publishing hard MTTR deltas fleet-wide — the numbers above reflect the shift we’ve observed so far.

Challenges we hit along the way

#ChallengeWhat went wrongHow we fixed it
1PagerDuty webhooks are scoped per serviceWith ~150 services, per-service webhook config doesn’t scaleUsed PagerDuty Incident Workflows — one rule, filtered by priority, covers every service
2Auth mismatchWebhook was set up with HMAC signing; the agent endpoint expects Bearer token authRegenerated the webhook using API-key (Bearer token) auth
3Priority case mismatchPagerDuty urgency is lowercase (high); the agent schema requires uppercase (HIGH) — mismatched requests failed silentlyMapped urgency to uppercase inside the workflow’s webhook payload template
4Missing required fieldpriority wasn’t obviously required; omitting it returned HTTP 200 with no investigation triggeredAlways send the complete payload; test integrations with the minimal required fields first
5Second trigger path = noiseRunning New Relic as a second trigger alongside PagerDuty meant routine Kubernetes events also fired investigationsDisabled New Relic as a trigger, kept it as a data source — PagerDuty’s human-curated relevance filter is now the only gate

The meta-lesson across all five: more trigger sources isn’t more coverage — it’s more noise. Let your incident-management tool do the curation; that’s already where humans decided what’s worth waking someone up for.

Conclusion

Automating incident RCA compounds over time: every incident that gets auto-investigated is an engineer who sleeps through the night or stays focused on their sprint instead of pivoting between five tabs at 3 AM.

We built IntelliOps first, and that wasn’t wasted effort — it proved the MCP-based approach and told us exactly what a real solution needed: automated triggering, context headroom for complex incidents, de-duplication, native infrastructure visibility, and zero maintenance overhead. AWS DevOps Agent checked every box, and the MCP data layer we’d already built — ClickHouse, New Relic, Kubernetes — carried forward directly. We promoted the data layer and swapped the orchestration.

The integrations weren’t perfectly smooth out of the box — auth mismatches, case-sensitivity bugs, and alert noise are all real — but every one was solvable, and we’ve documented them here so you don’t have to rediscover them. If your on-call rotation is drowning in manual investigation toil, this is worth the investment: setup is measured in hours, the return in MTTR and on-call sanity.

Build the systems that do the boring work. Keep the humans for the interesting problems.

Author