hardikmurdiac20.com — Site Reliability Engineer IST · remote
Udaipur, India · UTC+5:30

Eight years in production. Currently Technical Lead SRE at CloudBolt.

HardikMurdia

I make large systems tell the truth about themselves — then make them faster, cheaper, and quieter on-call.

Technical Lead SRE for a cloud FinOps platform — owner of observability, reliability and the AI/agentic tooling layer. Before that, performance engineering on a compliance archive taking in five petabytes a day. Performance engineering, DevOps, CI/CD, distributed systems.

01 / Trace

Eight years as one trace. Bar length is time in role. Pick a span to read the work inside it.

Where the time went

20182020202220242026
career
8 yr 7 mo · in progress

Technical Lead SRE

CloudBolt Software · Aug 2024 – present · remote

Leading SRE for a cloud FinOps platform — owner of observability, reliability, and the AI/agentic tooling layer.

Observability platform

  • Architected the observability framework end to end — OpenTelemetry collectors carrying traces, metrics and logs — with multi-vendor export to Honeycomb and SigNoz.
  • Standardised instrumentation across services, so a new service arrives already emitting the right telemetry instead of being retrofitted later.

SLOs and incident response

  • Defined the SLI/SLO/SLA practice and error budgets, integrated with PagerDuty, CloudWatch and Incident.io so alerting tracks real user impact rather than host health.

Performance

  • Raised endpoint availability from under 85% to 99.9% through performance tuning of high-traffic APIs.
  • Cut the Mira landing page from 7 s to 500 ms by tracing it end to end, then ran spike and load tests ahead of peak to prove it held.
  • Resolved cold starts and timeouts across 63+ Lambda functions and their databases, using distributed tracing to find them.
Case study Mira’s landing page: 7+ s to 500 ms, and why it wasn’t cold starts
Starting point

Mira was a new product whose landing page took seven seconds to load, and the brief was to at least halve it. There was no tracing anywhere in the stack — no spans, no instrumentation, nothing to ask a question of. So the first job wasn’t the latency, it was building something that could see it.

Ruling out the UI

The network waterfall in devtools ruled out the front end immediately: the browser was waiting, not working. The time sat in the backend calls, GraphQL resolvers running on Lambda, and the same call varied wildly between requests — which is the signature of something other than the query being slow.

Before
Devtools network panel before optimisation: the actions request returns 1.3 MB in 7.92 seconds, signalPoliciesMinimal takes 1.80 seconds, and GraphQL calls run between 0.87 and 1.41 seconds.
After
Devtools network panel after optimisation: the actions request returns 67.4 kB in 1.29 seconds and every GraphQL call completes between 179 and 694 milliseconds.
Same page, same calls. The actions endpoint goes from 7.92 s to 1.29 s; every GraphQL call lands under 700 ms. Both panels cropped to name, status, size and time; repeated identity rows elided in the before shot. No values altered.
Instrumenting it

You cannot see inside a Lambda invocation from the outside, so I built the trace flow from zero — OpenTelemetry collectors through to Honeycomb — and instrumented the handler down to individual operations rather than stopping at the request boundary. That resolution is what made the next step possible.

tracer = configure_tracing("mira-actions")
dynamodb = None

def execute_query(key_expression=None, filter_expression=None, attribute_names=None,
				  attribute_values=None, sort_field=None, sort_direction=None):
	global dynamodb
	table_name = os.environ["MIRA_ACTIONS_TABLE"]

	try:
		with tracer.start_as_current_span("mira-action-read-execute-query") as parent:
			parent.set_attribute("db.system", "dynamodb")
			parent.set_attribute("db.table", table_name)

			# the 2.66 s was hiding in here
			with tracer.start_as_current_span("dynamodb-resource-initialization"):
				if dynamodb is None:
					dynamodb = boto3.resource("dynamodb")

			with tracer.start_as_current_span("dynamodb-table-access") as span:
				table = dynamodb.Table(table_name)
				span.set_attribute("dynamodb.table_name", table_name)

			kwargs = {}
			with tracer.start_as_current_span("dynamodb-query-construction") as span:
				if key_expression is not None:
					kwargs["KeyConditionExpression"] = key_expression
				if filter_expression is not None:
					kwargs["FilterExpression"] = filter_expression
				if attribute_names is not None:
					kwargs["ExpressionAttributeNames"] = attribute_names
				if attribute_values is not None:
					kwargs["ExpressionAttributeValues"] = attribute_values
				if sort_field is not None:
					kwargs["IndexName"] = f"tenant_id-{sort_field}-index"
					kwargs["ScanIndexForward"] = sort_direction == "asc"
				span.set_attribute("dynamodb.query_arguments", str(kwargs))

			with tracer.start_as_current_span("dynamodb-query-execution") as span:
				result = table.query(**kwargs)
				span.set_attribute("dynamodb.query_result_count", len(result.get("Items", [])))

			return result["Items"]
	finally:
		flush_traces()
Handler instrumentation. The spans are deliberately narrower than the function — init, table access, construction and execution are separated so the trace can say which one costs.Scroll sideways for full lines.
0s 2s 4s 6s 8s 10s app.handler mira-action-read-handler mira-action-read-query-params mira-action-read-get-actions mira-action-read-execute-query dynamodb-resource-initialization dynamodb-table-access dynamodb-query-construction dynamodb-query-execution DynamoDB.Query 11.779s 11.501s 23.4µs 11.019s 10.943s 2.660s 39.37ms 0.266ms 8.243s 8.163s Red spans = 92% of the request. Neither is the query being complex.
One request to the actions endpoint. 10 spans, 11.779 s. Redrawn from the Honeycomb trace; span offsets approximate, durations exact.Scroll sideways to see the full trace.
What it showed

Two spans owned almost the whole request. DynamoDB resource initialisation burned 2.66 s before a single query was constructed, and query execution took a further 8.24 s. Query construction itself — the part you’d suspect — took 0.27 ms.

The wrong answer

Our working assumption was cold starts, and the reflex fix for that is warming or provisioned concurrency. Both would have been wasted money. The cost was memory. boto3 assembles its entire API surface from JSON files on first use, and Lambda scales CPU with allocated memory — so an under-provisioned function spends seconds parsing service models before it has talked to anything. tecRacer measured this at more than 10× slower on 128 MB than on 1408 MB, which matched what our spans were showing. Adding concurrency would have made it worse: more containers, each paying the full initialisation.

The fix

Right-sized memory on the affected functions. Landing page load dropped from 7 s to roughly 500 ms; the actions endpoint went from 7.92 s to 1.29 s.

What I took from it

The instrumentation was the real deliverable. Without spans inside the handler, “the page is slow” and “probably cold starts” would both have stayed true, unfalsifiable, and useless — and the fix would have been more Lambda concurrency, which would have cost money and changed nothing.

AI and agentic tooling

  • Built Raccoon, an adversarial LLM code-review agent running in GitHub Actions CI, with a tree-sitter knowledge graph for context reduction and a model-agnostic backend — Codex evaluated in POC, standardised on Claude for better review quality at lower token cost — plus automated AI cost tracking.
  • Extended it into agentic AIOps triage on AWS Bedrock, and is rolling out agentic Jira-to-PR remediation — both broken out in full further down the page.

Cost and hardening

  • Optimised RDS PostgreSQL — indexing, autovacuum, WAL tuning, schema refinement — which enabled downscaling and $85K+ in annual AWS savings.
  • Migrated MongoDB clusters from Intel to Graviton with right-sizing, for $48K+ annually.
  • Hardened MongoDB by moving TLS 1.2 to 1.3 at the shard level, reducing open file descriptors and connection overhead.

Team

  • Lead and mentor a team of six engineers — workload distribution, debugging, analysis — now one of the highest-performing teams in the organisation.
  • Kubernetes
  • Platform engineering
  • OpenTelemetry
  • Honeycomb
  • SigNoz
  • AWS Bedrock
  • MCP
  • PostgreSQL
  • MongoDB
  • Python
02 / Deltas

The numbers I'd want to be asked about. Each one is a before and an after on the same system.

Measured change

  • Endpoint availability · CloudBolt <85%99.9%
  • Mira landing-page load · CloudBolt 7 s500 ms
  • Enterprise Archive throughput · Smarsh 30–40 docs/sec1,000 docs/sec
  • Load-test environment setup · Smarsh 2 days10 minutes
03 / Ledger

Annualised cloud savings, each one traced back to a specific change in a specific system.

What came off the bill

ChangePer year
Automated Storm cluster sizing and targeted scale-downSmarsh · ~$3,800/day$1.0M+
T-shirt sizing the environment estate against real per-customer throughputSmarsh · micro / mini / major$1.3M
Kafka cluster right-sizing across regionsSmarsh · live broker decommissioning$150K
Datadog-driven analysis across 19 regionsSmarsh · remainder of the $2M+ programme$550K+
Stabilising a critical microserviceSmarsh · RDS$300K
RDS PostgreSQL tuning and downscalingCloudBolt · indexing, autovacuum, WAL$85K
MongoDB Intel → Graviton migrationCloudBolt · with right-sizing$48K
Total identified$3.5M+
04 / Raccoon

An agentic loop from alert to pull request, with humans holding the last gate. Built at CloudBolt.

Closing the loop on triage

01

signal

Errors, latency regressions and query spikes surface through Scout APM, RDS Performance Insights and pg_stat_statements.

02

mcp server

An internally deployed MCP server fetches the logs and telemetry around the event, so the agent reasons over real evidence rather than a summary.

03

bedrock agent

Correlates the alert, gathers root-cause data, and writes a Jira epic with reproduction steps and the exact remediation commands. Posts to Slack with an engineer assigned.

04

jira → pr

On transition to In Progress, a Claude-powered agent writes the fix and opens a pull request against the right repository.

05

adversarial review · gate

The PR passes through LLM review built to argue against it, using a tree-sitter knowledge graph to keep token cost down on large diffs.

06

human review · required

Nothing merges without a person. The agents remove the tedium; they don't hold the pen.

Model-agnostic with swappable backends — Codex was evaluated in a POC, Claude standardised on for better review quality at lower token usage — with AI cost tracked automatically.

05 / Stack

Filled boxes are what I reach for first.

Tools of the trade

Observability

  • OpenTelemetry
  • Datadog
  • Honeycomb
  • SigNoz
  • Scout APM
  • CloudWatch
  • Distributed tracing
  • High-cardinality metrics
  • SLI / SLO · error budgets

Reliability & operations

  • Incident response
  • PagerDuty
  • Incident.io
  • Root-cause analysis
  • HA / DR
  • Capacity forecasting
  • Production Readiness Reviews

Cloud & infrastructure

  • AWS
  • EC2
  • RDS
  • Lambda
  • Fargate
  • S3
  • SQS
  • IAM
  • Glue
  • DocumentDB
  • Kubernetes
  • Platform engineering
  • Docker
  • Terraform
  • CloudFormation

AI & agentic systems

  • AWS Bedrock
  • MCP servers
  • Claude Code
  • Agentic Jira → PR
  • tree-sitter knowledge graphs
  • Token & cost optimisation

Data systems

  • PostgreSQL
  • MongoDB
  • Elasticsearch
  • Kafka
  • Storm
  • Zookeeper
  • RabbitMQ
  • Pivotal Cloud Foundry

Automation & languages

  • Python
  • Java
  • Scala
  • Shell
  • GitHub Actions
  • Concourse
  • BOSH
  • JMeter
  • Gatling
  • DORA metrics
06 / Contact

Happy to talk about reliability work, performance forensics, or where agents actually help on-call.

If something in production is lying to you, I'd like to hear about it.

Education

  • B.Tech, Computer Science — minor in Bioinformatics, 2017
  • Vellore Institute of Technology — 8.31 CGPA
  • Final-year IoT project awarded the highest grade

Certifications & training

  • System Design Cohort — Arpit Bhayani
  • Architecting on AWS — Accelerator
  • AWS RDS — KodeKloud
  • Infra Expert — AlgoExpert
  • Advanced SQL for query tuning
  • Functional Programming in Scala

Recognition

  • VP of Engineering — for establishing observability practice at CloudBolt
  • Product Owner — for the Storm 2.3 upgrade
  • Sr. Manager — for automating load-tool setup from three days to thirty minutes
  • Peer awards for non-historic import, load tooling, audio ingestion and custom-metric COGS