Granular Dependabot groups and getting error attribution right

Dependabot has a default behaviour that doesn't scale well: one pull request per outdated dependency. For a repository with a hundred dependencies, a run generates dozens of individual PRs. Most are low-risk patch bumps a developer approves without reading closely — which means either they pile up unreviewed, or people start rubber-stamping them, which defeats the point of the review.

Why grouping matters

Dependency grouping addresses this. Instead of one PR per package, you define groups — "all AWS SDK packages", "all testing libraries", "everything from this upstream source" — and Dependabot combines the relevant updates into a single PR. The result is far fewer PRs, each giving a complete picture of a set of related changes.

The work was moving several repositories from ungrouped or coarsely grouped configs to ones with more granular, purposeful groups. The granularity matters: a group defined as "all dependencies" is barely better than no grouping — you still get one huge PR — while groups built around logical cohesion ("packages released together from the same upstream source") give you something you can actually review with confidence.

Applying it across different stacks

The interesting part of rolling this out is that each repo has a different dependency structure. A Node logging library has nothing in common with a .NET error-handling library or a React frontend. For the Node libraries, grouping around major upstream sources makes sense; for the .NET library, the groups follow NuGet namespaces; for the frontend, it's a mix of framework packages, tooling, and application libraries, each with their own natural groupings. You can copy the structure of the YAML across repos, but you still have to think about what actually belongs together in each — and that thinking is the part you can't automate away.

Error source attribution in a shared library

The other change was about correctness in error reporting. A shared .NET library classifies errors and warnings across several services — capturing not just the message but its origin: which part of the system produced it. The origin is an enum, and one category was missing: a group of trip-related services whose errors weren't covered by any existing value. When those services produced an error, it either failed to classify or fell into a catch-all, making it harder to route the alert and slower to find the responsible team.

Adding the value is straightforward. The more interesting question is why it was missing. This is a common pattern with shared classification types — the enum gets defined early, before all the consumers are known, and then isn't kept in sync as new services adopt the library. The fix doesn't just make reporting more accurate; it removes the ambiguity that wastes on-call time. "The origin is unknown" means more digging before anyone can act; "the origin is the trip services layer" means the right team gets paged immediately.

Platform hardening as a steady-state activity

This is worth naming for what it is: platform hardening. Not new features, not architecture changes, but the continuous work of making the infrastructure more reliable, maintainable, and legible to the people who depend on it. A Dependabot config sits in a file almost nobody reads until dependency updates go wrong; an error-source enum is invisible to end users. Both keep a system that dozens of engineers work in daily manageable over time. The return is long-tailed and largely invisible, which is exactly why it tends to get deprioritised — and doing it consistently, even when nothing more exciting is on the board, is how a platform stays manageable.