<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kushagra</title>
    <description>The latest articles on DEV Community by Kushagra (@kushagra-devs).</description>
    <link>https://dev.to/kushagra-devs</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4018793%2Ff29a39fd-40c5-4fb5-9433-5ea63b445f11.png</url>
      <title>DEV Community: Kushagra</title>
      <link>https://dev.to/kushagra-devs</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kushagra-devs"/>
    <language>en</language>
    <item>
      <title>Postmortems that don't suck: the template we actually use (steal it)</title>
      <dc:creator>Kushagra</dc:creator>
      <pubDate>Mon, 17 Aug 2026 07:52:28 +0000</pubDate>
      <link>https://dev.to/kushagra-devs/postmortems-that-dont-suck-the-template-we-actually-use-steal-it-d8p</link>
      <guid>https://dev.to/kushagra-devs/postmortems-that-dont-suck-the-template-we-actually-use-steal-it-d8p</guid>
      <description>&lt;p&gt;I've read a lot of postmortems. Most of them are written for an audience that doesn't exist.&lt;/p&gt;

&lt;p&gt;They're five pages long. They have an "Executive Summary" for executives who will never open the doc. They have a root-cause section that stops at "human error" (never the root, always an excuse to stop digging). And they end with action items like "improve monitoring" — assigned to nobody, due never, closed by nobody.&lt;/p&gt;

&lt;p&gt;Then the same incident happens eight months later, and someone says "wait, didn't we write this up last time?" and nobody can find the doc.&lt;/p&gt;

&lt;p&gt;A postmortem has exactly one job: &lt;strong&gt;make the next incident shorter or prevent it entirely.&lt;/strong&gt; Everything in the document either serves that job or is theater. Here's the format we landed on after writing plenty of theatrical ones — it fits on one page, takes under an hour, and people actually read it. Template is at the bottom; steal it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The three failure modes that kill postmortems
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. They're written to assign blame while claiming not to.&lt;/strong&gt; Everyone says "blameless," then writes a timeline where one person's name appears eleven times. Here's the practical test of blamelessness: replace every name in the doc with a role ("the on-call engineer," "the reviewer"). If the story stops making sense, your postmortem was about a person, not a system. Systems can be fixed; shaming a person just teaches everyone to hide the next mistake — and hidden mistakes are how small incidents become big ones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. They're written too late.&lt;/strong&gt; Two weeks after the incident, memories have quietly rewritten themselves into a cleaner story than what happened. The messy truth — the ten minutes spent debugging the wrong service, the alert everyone swiped away — is exactly the valuable part, and it evaporates first. Draft the timeline within 48 hours, even if the meeting happens later.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Nobody can reconstruct what actually happened.&lt;/strong&gt; This one's structural. The incident lived across your alerting tool, an error tracker, three chat threads, a DM where the actual fix was discussed, and a deploy log. Assembling a truthful timeline means archaeology across five tools, so people skip it and write vibes instead. (This scattered-evidence problem is half of why I'm building &lt;a href="https://flowtux.com/blog/introducing-flowtux-for-on-call" rel="noopener noreferrer"&gt;triage that catches on-call alerts in one queue&lt;/a&gt; — but you don't need tooling to start: just make "paste timestamps into the doc &lt;em&gt;as things happen&lt;/em&gt;" an on-call habit. Future-you, doing archaeology at 5 PM on a Friday, will be grateful.)&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually belongs in the doc
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A timeline with timestamps, including the embarrassing parts
&lt;/h3&gt;

&lt;p&gt;Not a narrative — a table. When did the issue start (not when was it &lt;em&gt;detected&lt;/em&gt; — the gap between those two numbers is one of your most important findings). When did the first human notice. What did they try. What didn't work.&lt;/p&gt;

&lt;p&gt;The wrong turns are the whole point. "We spent 25 minutes restarting the API before realizing it was the database" is not embarrassing filler — it's the single most reusable finding in the doc, because the next person will make the same wrong turn unless you write it down.&lt;/p&gt;

&lt;h3&gt;
  
  
  "Why did our safeguards not catch this?" — the only root-cause question that matters
&lt;/h3&gt;

&lt;p&gt;Skip the Five Whys ritual if it doesn't suit you, but do not skip this question. Every incident that reaches production walked past every defense you have: tests, review, staging, alerts, rate limits. The bug is rarely the interesting part. The interesting part is the hole in the net.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why didn't tests catch it? &lt;em&gt;(No coverage there? Coverage exists but the case is untestable?)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Why didn't review catch it? &lt;em&gt;(Diff too big? Reviewer had no context? Rubber-stamp culture?)&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Why didn't alerts catch it before users did? &lt;em&gt;(This one hurts the most and teaches the most.)&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note the shape of these questions: they're all about the system. That's what blameless actually means — not "no accountability," but "the system failed, and the system is what we can change."&lt;/p&gt;

&lt;h3&gt;
  
  
  Three action items, maximum
&lt;/h3&gt;

&lt;p&gt;This is the most opinionated rule in our format, and the one I'll defend hardest.&lt;/p&gt;

&lt;p&gt;A postmortem with twelve action items produces zero completed action items. Twelve items means nobody prioritized, so the backlog will — which means none of them ship. Force the ranking: &lt;strong&gt;what are the three changes with the best ratio of "prevents recurrence" to "effort"?&lt;/strong&gt; Each one gets a single named owner (a person, not a team — a team owner is no owner) and a date. Everything else you thought of goes in a "considered but not doing" list, &lt;em&gt;with the reason&lt;/em&gt;. That list is quietly the most honest section of the doc, and it saves the next incident's responders from re-litigating ideas you already rejected.&lt;/p&gt;

&lt;p&gt;And track them. An action item that isn't checked four weeks later is a decision to accept the risk — fine, but make it a decision, not a drift.&lt;/p&gt;

&lt;h3&gt;
  
  
  A "how will we detect this next time?" line
&lt;/h3&gt;

&lt;p&gt;One sentence. If the answer is "same way — a customer will tell us," say so explicitly. Writing that sentence down is uncomfortable in exactly the way that gets a monitoring gap actually fixed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The template
&lt;/h2&gt;

&lt;p&gt;Copy this into your wiki. Ruthlessly delete any section you're tempted to add back — length is the enemy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# [YYYY-MM-DD] Short, searchable title (name the system + symptom)&lt;/span&gt;

&lt;span class="gs"&gt;**Impact:**&lt;/span&gt; Who/what was affected, for how long, how badly.
One sentence. Numbers if you have them.

&lt;span class="gs"&gt;**Detection gap:**&lt;/span&gt; Issue started HH:MM · detected HH:MM · by [alert / customer / luck]

&lt;span class="gu"&gt;## Timeline (UTC)&lt;/span&gt;
| Time  | What happened |
|-------|---------------|
| 09:12 | Deploy #482 ships |
| 09:14 | Error rate on auth-svc rises (no alert fires) |
| 09:31 | First customer report |
| 09:40 | On-call restarts API (wrong tree — 25 min lost) |
| 10:05 | DB connection pool identified as cause |
| 10:11 | Mitigated (rollback) |

&lt;span class="gu"&gt;## Why our safeguards missed it&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Tests:**&lt;/span&gt; …
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Review:**&lt;/span&gt; …
&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="gs"&gt;**Alerts/monitoring:**&lt;/span&gt; …

&lt;span class="gu"&gt;## Root cause&lt;/span&gt;
2–4 sentences. If it ends at "human error," keep digging —
what made the error easy to make and hard to catch?

&lt;span class="gu"&gt;## Action items (max 3)&lt;/span&gt;
| # | Change | Owner (person) | Due | Done? |
|---|--------|----------------|-----|-------|
| 1 |        |                |     |       |

&lt;span class="gu"&gt;## Considered but not doing&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; [Idea] — [reason we're accepting this risk]

&lt;span class="gu"&gt;## Next time, we'll detect this via&lt;/span&gt;
One sentence. Be honest if the answer is "we won't."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Anti-patterns to delete on sight
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;"Human error" as root cause.&lt;/strong&gt; It's where the analysis stops, never where the truth is.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;"Improve monitoring" as an action item.&lt;/strong&gt; Which monitor? On what threshold? Owned by whom? Vague items are unfalsifiable, and unfalsifiable items are never done.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Word-doc graveyard.&lt;/strong&gt; If postmortems aren't searchable from where engineers already work, they might as well not exist. The doc's title should contain the system name and the symptom, because that's what the next responder will frantically search for at 2 AM. ("We wrote this up last time" is only useful if last time is findable — the same reason &lt;a href="https://dev.to/kushagra-devs/how-do-you-dedupe-support-tickets-that-dont-share-any-words-heres-our-messy-attempt-d5g"&gt;duplicate tickets are a search problem before they're an AI problem&lt;/a&gt;.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Postmortems only for big incidents.&lt;/strong&gt; The 20-minute near-miss teaches the same lesson as the 4-hour outage, at 5% of the cost. Write the small ones; they're cheaper tuition.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The uncomfortable summary
&lt;/h2&gt;

&lt;p&gt;If your postmortems are long, late, blameful, and unfindable, people will treat them as punishment paperwork — and you'll get exactly the quality of analysis that punishment paperwork deserves. Make them one page, fast, systemic, and searchable, and they become the cheapest reliability investment you can make.&lt;/p&gt;

&lt;p&gt;What's the best (or most cursed) postmortem practice you've seen at your company? Genuinely collecting these — the "considered but not doing" section above was stolen from a comment on a previous post.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>beginners</category>
      <category>sre</category>
      <category>devops</category>
    </item>
    <item>
      <title>Your Engineering Team's Biggest Bottleneck is Slack</title>
      <dc:creator>Kushagra</dc:creator>
      <pubDate>Sun, 02 Aug 2026 18:22:59 +0000</pubDate>
      <link>https://dev.to/kushagra-devs/your-engineering-teams-biggest-bottleneck-is-slack-48o3</link>
      <guid>https://dev.to/kushagra-devs/your-engineering-teams-biggest-bottleneck-is-slack-48o3</guid>
      <description>&lt;p&gt;For most engineering teams, this is a painfully familiar story:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A PagerDuty alert fires at 2 AM.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The on-call engineer sees it, rolls over, and posts the Sentry link in the #dev-urgent Slack channel.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They @mention the original author of the code, the team lead, and maybe one other senior engineer for good measure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;They go back to sleep, assuming the problem is now "handled."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next morning, the team wakes up to a sea of notifications, but zero ownership. The error is still there, nobody has touched it, and three different people have now created three different Jira tickets for the same underlying issue.&lt;/p&gt;

&lt;p&gt;This isn't a process. It's a cry for help disguised as a workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Hidden Cost of Chat-Driven Triage
&lt;/h2&gt;

&lt;p&gt;Using Slack or Teams as your de-facto incident management tool feels free, but it's one of the most expensive decisions an engineering-led company can make. The cost isn't in dollars; it's in lost focus, duplicated work, and engineer frustration.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;No Clear Ownership : An @mention is not an assignment. When you notify everyone, you notify no one. The responsibility is diffused across the entire group, leading to bystander apathy.&lt;br&gt;
No Durable Record: Slack is a river. Critical context, logs, and screenshots get washed downstream within hours. When the same issue reappears next month, you're starting the investigation from scratch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;No Deduplication : Chat has no concept of semantics. The same database error can trigger 10 different alerts from 5 different tools, and each one will get its own thread, creating a storm of noise that hides the real signal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Constant Interruption : Every notification pulls engineers out of deep work to assess the same problem. You're paying for your entire team's context-switching, not just the one person who will eventually fix the issue.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Moving from Chaos to Clarity
&lt;/h2&gt;

&lt;p&gt;The solution isn't to ban Slack. It's to treat incident response with the same seriousness as you treat your production code. It needs a clear, structured, and automated workflow.&lt;/p&gt;

&lt;p&gt;At Mecverse, we live this problem, and it's why we built &lt;a href="https://flowtux.com" rel="noopener noreferrer"&gt;FlowTux&lt;/a&gt;. Our internal process, powered by our own tool, looks like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A Single Point of Ingestion : All signals—from chat, issue trackers, observability tools, and customer portals—feed into one place.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;AI-Powered Triage : Before a human is ever notified, an AI layer categorizes the issue, sets a priority, and, most importantly, blocks any semantic duplicates. That storm of 50 alerts for one database issue becomes a single, actionable ticket.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Code-Grounded Context : The ticket arrives with the stack trace already mapped to the exact files in our codebase that are responsible. The investigation is already 90% done.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automated Resolution (with Guardrails) : For a known set of problems, a sandboxed agent can run a pre-approved command (like clearing a cache or restarting a pod) and close the ticket automatically.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This isn't about replacing engineers. It's about protecting them. It's about automating the tedious, soul-crushing parts of triage so they can focus on what they do best: building and solving complex problems.&lt;/p&gt;

&lt;p&gt;If your incident response plan starts with an @mention, it's time for an upgrade.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>sre</category>
      <category>management</category>
    </item>
    <item>
      <title>How do you dedupe support tickets that don't share any words? Here's our messy attempt.</title>
      <dc:creator>Kushagra</dc:creator>
      <pubDate>Tue, 07 Jul 2026 09:58:09 +0000</pubDate>
      <link>https://dev.to/kushagra-devs/how-do-you-dedupe-support-tickets-that-dont-share-any-words-heres-our-messy-attempt-d5g</link>
      <guid>https://dev.to/kushagra-devs/how-do-you-dedupe-support-tickets-that-dont-share-any-words-heres-our-messy-attempt-d5g</guid>
      <description>&lt;p&gt;We build an internal helpdesk, and I want to talk through a problem we only partly solved — because I suspect a lot of you have hit it too, and I'd genuinely like to hear how you handled it.&lt;/p&gt;

&lt;p&gt;The most requested thing from our users was never "better ticket forms." It was "please make the duplicates stop."&lt;/p&gt;

&lt;p&gt;Here's the shape of it. A deploy goes slightly wrong at a 40-person company. Within ten minutes you have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a handful of &lt;strong&gt;chat messages&lt;/strong&gt;: "login is broken", "can't get into dashboard???", "deploy looks weird"&lt;/li&gt;
&lt;li&gt;several &lt;strong&gt;error-tracker events&lt;/strong&gt; (whatever you run — Sentry, Rollbar, an APM): &lt;code&gt;TokenExpiredError&lt;/code&gt; ×2, a 401 spike on &lt;code&gt;/api/auth&lt;/code&gt;, a 5xx spike on &lt;code&gt;auth-svc&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;a couple of &lt;strong&gt;emails to IT&lt;/strong&gt;: "access token expired", "need login reset"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nine items across three channels. One root cause: token rotation broke in that deploy. Whoever's on rotation spends the morning proving that, instead of fixing anything.&lt;/p&gt;

&lt;p&gt;We wanted to automate the &lt;em&gt;recognition&lt;/em&gt; step — "these are the same thing" — not the fixing step. This is the honest version: what we tried, the small thing we actually shipped, and the parts we haven't cracked. If you've built something similar, I'd love to be told what we got wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt 1: rules and keywords (broke immediately)
&lt;/h2&gt;

&lt;p&gt;The obvious first cut: normalize ticket text, match on keywords and categories, merge on high overlap.&lt;/p&gt;

&lt;p&gt;It fails on the example above, and it fails structurally: "login is broken" and &lt;code&gt;TokenExpiredError&lt;/code&gt; share zero tokens. The human on rotation isn't string-matching — they know a deploy just happened, they know what auth-svc does, they've seen this failure shape before. Rules encode none of that.&lt;/p&gt;

&lt;p&gt;Rule systems also rot. Every incident teaches you a new synonym for "it's down," and six months in you own a regex museum nobody wants to touch. Maybe you've kept one of these healthy long-term — if so I'd honestly like to know how.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt 2: embed everything, cluster by similarity (the one we didn't ship)
&lt;/h2&gt;

&lt;p&gt;The tempting next move: embed ticket text, cluster on cosine similarity, call anything close enough a duplicate.&lt;/p&gt;

&lt;p&gt;We already use embeddings elsewhere in the product — for retrieving relevant &lt;em&gt;code context&lt;/em&gt; from a customer's repo, not for tickets. When we thought about pointing the same machinery at ticket dedup, two things gave us pause:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;It can't cross the complaint/cause gap.&lt;/strong&gt; "Can't get into dashboard???" and &lt;code&gt;TokenExpiredError at auth.rotate_credentials&lt;/code&gt; aren't semantically similar — they're related only through a fact that lives outside both tickets (the deploy). Embedding text you don't have doesn't help.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pure text similarity produces confident false merges.&lt;/strong&gt; "Dashboard is slow" and "dashboard is broken" embed close together and often have unrelated causes. And a false merge is the expensive failure: a missed duplicate wastes a few minutes; a wrong merge buries a real incident inside an unrelated one.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So we didn't ship the vector-clustering pipeline for tickets. It felt like a lot of moving parts to end up with &lt;em&gt;worse&lt;/em&gt; precision on exactly the merges we most wanted to get right. Possible we were wrong to skip it — if you've made embedding-based dedup work well, I'd love to hear what made the difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attempt 3: what we actually shipped — one strict Tux AI call
&lt;/h2&gt;

&lt;p&gt;The version in production is deliberately small. When a new ticket arrives, we make a single &lt;strong&gt;Tux AI&lt;/strong&gt; call (our own triage model, tuned low-temperature for consistency) that gets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the new message text&lt;/li&gt;
&lt;li&gt;a &lt;strong&gt;small&lt;/strong&gt; candidate list of existing open tickets (title / description / status)&lt;/li&gt;
&lt;li&gt;optionally, code context to disambiguate which part of the app is meant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The prompt is short and strict — the load-bearing instruction is roughly &lt;em&gt;"only mark this a duplicate when it's genuinely the same underlying issue; be strict."&lt;/em&gt; The model returns a duplicate flag, the matched ticket, and a confidence score. That's the whole dedup engine. No embeddings, no clustering, no vector store for tickets.&lt;/p&gt;

&lt;p&gt;Two choices are doing most of the work:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The candidate set is tiny on purpose.&lt;/strong&gt; We don't ask "is this a duplicate of anything, ever?" We ask "is this a duplicate of &lt;em&gt;these few&lt;/em&gt; open tickets?" — the reporter's own open tickets on the chat intake path, or a short list of recent open tickets from the same source on the monitoring path. A small, same-source candidate list is what keeps a fast model accurate. It's also our biggest limitation — more below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;We tuned the threshold toward precision.&lt;/strong&gt; Duplicate handling only fires on high confidence. Below that, the ticket just gets created normally. We'd rather miss a duplicate than merge two things that shouldn't be.&lt;/p&gt;

&lt;p&gt;What "duplicate" &lt;em&gt;does&lt;/em&gt; depends on the channel, and here's a rough edge I'm not proud of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chat intake:&lt;/strong&gt; if the new message looks like a duplicate, we route the reporter to &lt;em&gt;update the existing ticket&lt;/em&gt; instead of opening a new one. Non-destructive, reversible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring intake (error trackers, alerting):&lt;/strong&gt; if a new event matches an existing open ticket, we &lt;strong&gt;drop the new event silently&lt;/strong&gt; — no comment, no link, no "merged because…" record. It just doesn't get created.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That silent drop is the part that keeps me up a little, and it leads into the honest limitations.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we haven't cracked (and would take advice on)
&lt;/h2&gt;

&lt;p&gt;I'll be blunt, because dev.to comments are unforgiving and I'd rather you trust the parts that &lt;em&gt;are&lt;/em&gt; true:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No stored merge reason.&lt;/strong&gt; The confidence and matched-ticket come back, route the request, and then get discarded. We don't persist a "merged because all reference auth failures after deploy #482" string yet. We want to — an auditable, reversible merge record is the next thing on the list — but it doesn't exist today.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No cross-channel dedup.&lt;/strong&gt; A chat complaint, a monitoring event, and an email about the same outage are compared only within their own channel's candidate list. The nine-item example that opens this post? We'd catch some same-channel duplicates and miss the cross-channel links. Unifying those channels into one queue is &lt;a href="https://flowtux.com/blog/one-inbox-slack-sentry-github" rel="noopener noreferrer"&gt;the direction we're building toward&lt;/a&gt;, but honest dedup &lt;em&gt;across&lt;/em&gt; them is still open.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The silent monitoring drop.&lt;/strong&gt; No audit trail on a suppressed event means when the model is wrong, nobody can see why. First thing we're fixing: link the dropped event to the ticket it matched and store the reasoning, so a bad drop is debuggable.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Slow-burn duplicates.&lt;/strong&gt; Two tickets a week apart about the same flaky config rarely connect — not in each other's small, recent candidate window.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The first ticket of an incident.&lt;/strong&gt; By definition there's nothing to match it against, so confidence is worst exactly when the incident is quietest. The system gets more useful as the incident gets louder, which is backwards from what you'd want.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The thing we think unlocks the rest — and are building now
&lt;/h2&gt;

&lt;p&gt;The gap under all of these is that the tickets don't carry their own cause. The human on rotation solves it by knowing the &lt;em&gt;state of the world&lt;/em&gt;: auth-svc deployed at 10:02, &lt;code&gt;TokenExpiredError&lt;/code&gt; started 10:04, the dashboard depends on auth, therefore these are one incident.&lt;/p&gt;

&lt;p&gt;So the piece we're actively working on is &lt;strong&gt;service-topology / blast-radius reasoning&lt;/strong&gt; — a dependency map plus deploy timing, so "auth-svc is failing" can &lt;em&gt;explain&lt;/em&gt; "dashboard logins are failing" even when the tickets share no words. If it works, cross-channel dedup and the "first ticket of an incident" problem both get easier: you're correlating on shared cause, not shared text.&lt;/p&gt;

&lt;p&gt;I'm genuinely unsure of the right shape here, and this is the part I'd most like a reality check on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do you get a &lt;strong&gt;trustworthy&lt;/strong&gt; service dependency graph without asking every team to hand-maintain one that goes stale in a month?&lt;/li&gt;
&lt;li&gt;Deploy-time correlation feels powerful but noisy — how do you keep "something shipped recently" from swallowing every unrelated ticket in the window?&lt;/li&gt;
&lt;li&gt;For those of you running incident tooling: does topology actually pull its weight, or is it the feature that demos well and rots in prod?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Takeaways so far
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deduplication is a "shared cause" problem wearing a "text similarity" costume.&lt;/strong&gt; The cause usually isn't written in the tickets.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A small, same-source candidate set beats a clever global search&lt;/strong&gt; for keeping a fast model accurate — at least until you have real cause signals to correlate on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tune for precision; false merges are the expensive failure.&lt;/strong&gt; The costs aren't symmetric, so the threshold shouldn't be.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;If your dedup path is destructive, make it auditable and reversible before you make it smart.&lt;/strong&gt; A silent correct drop and a silent wrong drop look identical to the humans who have to trust the system.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you've built ticket dedup, incident correlation, or topology-aware triage — especially the topology part — I'd really like to hear what worked and what you'd never do again. That's mostly why I wrote this.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;I work on &lt;a href="https://flowtux.com" rel="noopener noreferrer"&gt;FlowTux&lt;/a&gt;, where this dedup path runs across chat, email, and monitoring intake. We're building toward &lt;a href="https://flowtux.com/blog/one-inbox-slack-sentry-github" rel="noopener noreferrer"&gt;one deduplicated inbox across your alerting, error tracking, and code&lt;/a&gt; — the topology piece above is the current frontier. Happy to go deeper in the comments, including the parts that still embarrass us.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
