The dependency update policy decision record: why the update cadence you chose determines your dependency debt accumulation surface and your unpatched vulnerability window
Dependency update policies are set in a founding session that specifies a pinning strategy or an update cadence without documenting the maximum version lag, the security update SLA, or the behavioral change detection requirement for automated tooling. Three failure patterns follow from this gap: the team that defers a major version upgrade for stability, accumulates three years of version lag, and discovers that the security patch for an active CVE is only available in the major version they kept deferring (the founding session documented "pin to current versions for stability" without specifying the maximum lag before a required upgrade, or how security patches would be handled when they require crossing a deferred major version boundary); the team that enables auto-merge for CI-passing Dependabot PRs to control queue depth and discovers six weeks later that a patch version update silently changed how a billing library formats credit adjustment values — no test failed because no test covered the display format of a credit adjustment, and the auto-merge policy never required changelog review for libraries with customer-facing output; and the team that routes all dependency updates through the same sprint triage process and learns, after 47 days, that a critical CVE remediation timeline exceeded the 30-day SLA the company had committed to in a customer contract.
A 31-person SaaS company built its backend on Node.js 14, pinned in the first month of production with the documented rationale: "We pin to the current LTS release for stability. Updates are evaluated when we have bandwidth." The dependency pinning decision was sound for its moment — Node.js 14 was the active LTS and the team had enough on their plate building the product. The decision was not revisited in year one because nothing broke. It was not revisited in year two because the sprint backlog was full and the team had grown to the point where changing the runtime felt like a significant coordination cost. It was not revisited in year three until it became impossible to ignore.
By the time an engineer named Marcus raised the Node.js upgrade question in year three, Node.js 14 had reached end-of-life fourteen months earlier. The current LTS was Node.js 20. Marcus spent a week surveying the upgrade path: the team's codebase used 47 direct dependencies, of which 12 had published breaking changes between their Node.js-14-compatible versions and their Node.js-20-compatible versions. The most significant was a gRPC client library whose API surface had changed substantially in two major versions — the change required reworking the initialization pattern, the streaming interface, and the error handling model in eleven service-to-service communication paths. Marcus estimated the total upgrade effort at four to six weeks of engineering time, assuming no unexpected compatibility issues surfaced during the migration. The team had a two-week sprint and a roadmap full of customer-committed features. The upgrade was added to the backlog as a Q3 priority.
Seven weeks into Q3, a CVE was published against the npm package vm2: a sandbox escape vulnerability rated CVSS 10.0 — the maximum possible score. The team's backend used vm2 to execute user-submitted webhook transformation scripts in an isolated context. The CVE allowed a carefully crafted transformation script to break out of the sandbox and execute arbitrary code in the host Node.js process. The vm2 maintainers responded within 48 hours: they published a patched version and simultaneously announced that vm2 was deprecated, that all future security work would be in a successor library called isolated-vm, and that the patch was available for the current major version of Node.js only — not for Node.js 14, which had been end-of-life for over a year.
Marcus looked at the options. Migrating to isolated-vm required Node.js 16 at minimum and Node.js 18 for the full API. Applying the patch to vm2 was not an option — no patch existed for Node.js 14. The local workaround — running transformation scripts in a child process with restricted permissions — was implementable in two to three days but did not close all of the CVE's attack surface; the isolation it provided was weaker than the patched vm2 version and required a threat model justification to document its limitations honestly. The four-to-six-week Node.js upgrade was now blocking a critical security patch on a CVSS 10.0 vulnerability in a component that executed user-supplied code.
The team shipped the child process workaround in three days, documented its limitations, and began the Node.js upgrade under emergency conditions — with a compressed timeline, a full sprint of customer commitments already in flight, and an active security exposure that the engineering lead had to explain to the company's largest enterprise customer. The workaround held. The upgrade completed in five and a half weeks. No customer data was compromised. But the incident cost three unplanned engineering weeks, a delayed roadmap commitment, and an uncomfortable customer conversation about a vulnerability that had been live in the product for eleven days before the mitigation shipped.
The founding session that documented "pin to current LTS for stability" had not specified the maximum lag between a major release and a required upgrade. It had not specified what would happen when a security patch was only available in a version that required crossing the accumulated migration debt. And it had not identified which dependencies in the stack were executing user-supplied input — the category where a CVSS 10.0 sandbox escape is not a theoretical concern but a direct product risk. Three years of reasonable, sprint-driven deferral had converted a stability policy into a security constraint.
A 29-person product SaaS enabled Dependabot for all dependencies in month two and configured it to open pull requests for every available update on a weekly schedule. By month four, the team had 140 open Dependabot pull requests. The pull requests were not being merged. Engineers opened them, saw that the CI check had passed, noted that the library was a patch or minor update, and deprioritized the review in favor of feature work. New Dependabot PRs opened every week. The queue grew.
An engineering lead named Sofia decided to address the queue depth problem. She proposed auto-merging any Dependabot PR where CI passed — this was a common configuration, used by many open source projects and recommended in the Dependabot documentation for patch updates. The team agreed. Sofia configured the auto-merge rule, the 140-PR backlog collapsed to zero over a weekend as CI ran through the queue, and the team's dependency maintenance overhead dropped to near-zero. The next few months, Dependabot PRs were opened, CI ran, and PRs merged automatically. No engineer needed to review them.
Six weeks after the auto-merge policy went live, a customer named Daniel sent a support email. He was reviewing the monthly billing report that WhyChose generated for his team's account — a PDF that listed all subscription events, seat changes, and credit adjustments for the month. He had applied a credit adjustment for a seat downgrade in week two, and the credit appeared in the report as a positive number rather than a negative one. He wanted to confirm whether the amount would be deducted from the next invoice or added to it. It was a reasonable question, and the support engineer who received it immediately knew the answer — credits reduce the next invoice — but the question prompted him to pull up the billing report template to point Daniel to the right line.
The credit adjustment line showed a positive number. It should have shown a negative number. The support engineer opened a staging version of the billing report for a test account with a credit adjustment and saw the same behavior — positive number, no minus sign, no parentheses, no indicator that this was a deduction rather than a charge.
The engineering team traced the change to a Dependabot PR that had been auto-merged forty-three days earlier: a patch update to moment from version 2.29.3 to 2.29.4. The update had addressed a date parsing regression and was listed as a patch release with no breaking changes in the npm changelog. The patch included a fix to how negative durations were handled in moment.duration().humanize() — a method the billing report used to format the description of credit adjustments. In version 2.29.3, a negative duration formatted with the suffix option produced output like "-2 days"; in version 2.29.4, the same call produced "2 days ago" — the library had changed the human-readable framing. The billing report used the numeric value from the duration formatting as the displayed credit amount. The change did not produce an error. CI passed because the billing report's test coverage covered the report generation path for positive charges but not for credit adjustments — credit adjustments were a newer feature, added in month six, and the test had been added to the backlog as a "nice to have."
The team corrected the formatting bug, shipped a fix in two days, and retroactively regenerated billing reports for all accounts that had credit adjustments in the previous six weeks. Twelve accounts were affected. No customer had overpaid or underpaid — the credit adjustment amounts were correct in the database and applied correctly to invoices; only the display format in the PDF report was wrong. But two customers had made billing decisions based on the PDF report, and both required individual calls to confirm the correct credit amounts. The remediation took four engineering days plus two customer success hours.
The founding session had not addressed auto-merge at all — Dependabot was configured later, and the auto-merge policy was adopted later still as a practical response to queue accumulation. But the absence of a policy meant that when Sofia designed the auto-merge configuration, there was no established principle for which updates required changelog review and which did not. The auto-merge policy treated a patch update to a formatting library that appeared in customer-facing billing PDFs the same way it treated a patch update to a test runner or a build tool. CI-green was the only gate, and CI-green does not detect behavioral changes in output that no test covers.
A 38-person B2B SaaS ran a security program that they were proud of: a SAST scanner in CI, a penetration test every six months, and a monthly review of Dependabot's security alert queue. The monthly review was the mechanism by which security alerts were converted into engineering work. An engineer pulled the security alert list from the GitHub Security tab, created GitHub issues for each open alert, assigned them to the sprint backlog, and let the sprint planning process prioritize them against feature work. This process had worked well for the company's first three years because the security alerts that had appeared were all medium or low severity — CVSS scores between 4 and 7, mostly in dev dependencies, almost all with straightforward patches that took less than a day to apply.
In month 37, a critical CVE was published in log4j-node, a Node.js logging library the company had adopted in year one because the engineering lead at the time had worked in a Java environment where log4j was standard and the Node.js port felt familiar. The CVE allowed a remote attacker to trigger arbitrary code execution by crafting a log message that contained a JNDI lookup string — effectively the same class of vulnerability as Log4Shell, applied to the Node.js port. The CVSS score was 9.8.
The Dependabot security alert appeared in the GitHub Security tab the same day the CVE was published. An engineer named Priya added it to the issue tracker during the next monthly security review — three weeks after the CVE publication. She created a GitHub issue titled "Update log4j-node — CVE-2026-XXXX (Critical)" and added it to the engineering backlog. Sprint planning occurred the following Monday. The issue competed for sprint slots against a high-priority customer integration feature, two bug reports, and a performance investigation. The engineering lead assigned the two bug reports and the performance investigation to the sprint. The CVE fix and the integration feature were bumped to the next sprint as "next up — important."
Forty-seven days after the CVE was published, the company's VP of Sales received an email from a prospect's security team. The prospect had been in late-stage negotiations for an enterprise contract and had conducted a vendor security review that included a scan of publicly disclosed CVEs against the vendor's known technology stack. The security team had found the unpatched log4j-node CVE. The email asked for the company's remediation timeline. The prospect's security addendum — the same template the company had signed with three existing enterprise customers — required vendors to remediate critical vulnerabilities within 30 days of CVE publication.
The VP of Sales forwarded the email to the CTO. The CTO asked the engineering lead when the CVE would be patched. The engineering lead checked the backlog: the issue was scheduled for the current sprint, which had started two days earlier. The patch would ship within the sprint — approximately twelve days. But the question the prospect was actually asking was whether the company had a critical vulnerability remediation process that guaranteed 30-day remediation. The honest answer was: the company had a monthly security review and a sprint-based prioritization process that had produced a 47-day timeline for this CVE.
The patch shipped nine days later, at day 56 from CVE publication. The company negotiated the enterprise contract successfully — the prospect accepted a written explanation of the remediation and a commitment to implement a formal critical CVE SLA in the engineering process. But the negotiation required the CTO to participate in two calls explaining the incident, the remediation timeline, and the policy changes being implemented. The contract was delayed by three weeks.
The founding session had documented the security tooling: SAST in CI, Dependabot alerts enabled. It had not documented the security update SLA. It had not specified that critical CVEs required a different prioritization track from the sprint backlog. It had not cross-referenced the customer contract template, which included a 30-day critical vulnerability remediation requirement that the engineering team had never been made aware of. The monthly security review process and the sprint-based prioritization were reasonable defaults for the early-stage company — they were also incapable of producing a 30-day remediation timeline for any CVE that arrived mid-sprint and competed with customer-committed feature work.
Structural properties set by the dependency update policy decision
Three structural properties are determined when a team decides how to handle dependency updates. None appear explicitly in the session that configures the dependency manager, enables the security scanning tooling, or sets the initial version pins — they are operational characteristics that emerge from the update policy's assumptions about version lag, automation scope, and the relationship between dependency maintenance and security obligations.
Property 1: The update cadence and the dependency debt accumulation surface. Dependency debt is the compound distance between the versions a codebase runs and the current stable releases of each dependency. It accumulates incrementally with each deferred major version upgrade and grows faster than teams expect because major versions of actively maintained libraries ship every twelve to thirty-six months for most of the ecosystem. The surface that dependency debt creates is not merely operational inconvenience — it is a constraint on the team's ability to apply security patches. Most library maintainers backport security patches for one minor version series beyond the current major release, and not beyond that. A team running three major versions behind on a logging library, a cryptography library, an HTTP client, or any library that processes external input cannot apply a security patch without first completing the migrations they deferred. The debt converts from an engineering backlog item into a security incident at the moment a CVE is published against a version that is no longer receiving security backports — a moment that is directly determined by how far behind the team has allowed the version lag to accumulate. The structural requirement is a version lag ceiling: for every production dependency, document the maximum number of major versions the codebase is permitted to run behind the current stable release before a migration is required. Two major versions behind is a common threshold that keeps the codebase within the security backport window for most actively maintained libraries. The ceiling converts a deferral that is individually reasonable ("we don't have bandwidth this sprint") into a policy that prevents the accumulation of debt that blocks future security patches. The package dependency management decision record documents the pinning model — whether the team pins exact versions, uses lockfiles, or allows floating ranges — which determines the baseline version discipline; the update policy document specifies when and how that baseline is advanced, which determines whether the pinning discipline produces a stable codebase or a progressively outdated one.
Property 2: The automated update signal and the behavioral change detection gap. Automated dependency tooling (Dependabot, Renovate, Snyk) generates pull requests that carry a CI pass or fail signal. They do not carry a behavioral change signal. A patch or minor version update that passes CI can still change the output of a customer-facing calculation, alter the format of a date or currency value, modify the set of HTTP headers sent in an outbound request, change the order of keys in a serialized JSON response, or shift the timing of an async operation in a way that introduces a race condition no existing test covers. The behavioral change detection gap is the set of behaviors the library exhibits in production that the CI suite does not exercise. For libraries whose output appears in customer-facing responses — formatting libraries, serialization libraries, HTTP clients, PDF generation libraries, email composition libraries — this gap is always non-zero, because test suites are written against the behaviors engineers knew about at the time they wrote the tests, not against the behaviors a future patch version will change. The structural requirement is a classification of dependencies by their production-facing surface: infrastructure-only dependencies (test runners, build tools, linters, type checkers, dev dependencies with no runtime production path) can be auto-merged on CI pass because a behavioral change in a linter does not affect customers; production libraries with customer-facing output require changelog review before merge, because a behavioral change in a date formatting library may affect customers even when CI passes. This classification must be documented in the update policy ADR — not inferred by individual engineers reviewing individual PRs — because the auto-merge configuration is a blanket policy, and the blanket will cover the billing report formatting library as fully as it covers the ESLint configuration. The CI/CD pipeline decision record specifies which tests run on dependency update PRs; this document specifies which dependencies require human changelog review before merge, which is the complement to the CI gate — the gate catches regressions in behaviors the tests cover; the review catches behavioral changes in behaviors the tests do not cover.
Property 3: The security update SLA and the unpatched vulnerability window. The unpatched vulnerability window is the interval between a CVE publication date and the date a patched version is deployed to production. In teams without a security-specific update SLA, the window is determined by sprint capacity, engineering priorities, and the queue depth of the security alert backlog — not by the severity of the vulnerability or any contractual commitment the company has made to customers. This is the structural mismatch: the sprint-based prioritization process is designed to balance feature work against maintenance work based on team capacity; it is not designed to enforce an external time constraint on any category of work. A critical CVE that arrives mid-sprint competes with features already committed to customers; the prioritization outcome is a function of the sprint's existing commitments, not the CVE's severity. The structural requirement is a separate prioritization track for security updates that operates outside the sprint backlog and enforces a documented SLA per severity level. Critical CVEs (CVSS 9.0–10.0) typically require a 7–14-day remediation timeline; high severity (CVSS 7.0–8.9) requires 30 days; medium severity (CVSS 4.0–6.9) requires 90 days. These timelines must be cross-referenced with any customer contract security addendums, SOC 2 control commitments, or security questionnaire responses the company has made — because the binding SLA is the most restrictive commitment across all external obligations, not the internal default. The incident response playbook decision record documents the escalation path and communication requirements for active security incidents; the dependency update policy ADR specifies the preventive process — the SLA that is meant to ensure the incident response playbook is never needed for a vulnerability that had a patched version available and a documented timeline for applying it.
What the founding session records and what it omits
The founding dependency update session — typically part of a broader "how do we manage code quality and dependencies" conversation in the first month of production — records the tooling choice (Dependabot enabled, Renovate configured, Snyk license tier selected) and sometimes the initial update cadence (weekly, monthly, manual). What it does not record is the operational policy that the tooling requires to produce the correct behavior over time: the version lag ceiling, the dependency classification for auto-merge eligibility, the security update SLA, and the cross-reference to contractual obligations.
The omission is structurally similar to every other founding-session decision covered in this series: the failure modes are theoretical at founding, when the dependency list is short, the version lag is zero, and the team that configured Dependabot is the same team that reviews every PR. A version lag ceiling is unnecessary when you are running the current version. A classification of customer-facing vs. infrastructure-only dependencies is unnecessary when there are eight dependencies and you read every changelog personally. A security update SLA is unnecessary when there have been no security alerts and no enterprise contracts specifying remediation requirements.
The failure modes become visible over time. The version lag accumulates in increments of individual reasonable deferrals, each one invisible until the compound total creates a constraint on future security patches. The auto-merge policy covers a codebase that has grown to include new libraries whose output appears in new customer-facing features built after the auto-merge rule was configured. The enterprise contract security addendum arrives in a sales process that postdates the founding session by two years. And the process that was adequate for a twelve-dependency codebase with no enterprise customers and no security obligations is still running, unchanged, when the dependency list is 200 and the company's contractual obligations include a 30-day critical CVE SLA.
The dependency update policy ADR closes this gap by recording the four commitments that the tooling configuration implies but does not enforce: the version lag ceiling (the maximum major version distance before migration is required), the auto-merge eligibility policy (which dependency categories require changelog review and which can merge on CI pass), the security update SLA (the maximum days per severity level, cross-referenced to the most restrictive external obligation), and the end-of-life policy (the trigger for migration when a dependency's maintainers announce end-of-life support). These are the commitments that distinguish a dependency maintenance practice from a dependency maintenance process — the difference between "we have Dependabot enabled" and "we have documented that no production dependency runs more than two major versions behind current stable, that patch updates to formatting and serialization libraries require changelog review before merge, that critical CVEs are patched within 14 days per our SOC 2 control commitment and our most restrictive customer contract, and that any dependency announcing end-of-life prompts a migration within 90 days." The first statement describes the tooling. The second describes the decision. The decisions never written down are rarely the tooling choices — "we use Dependabot" appears in every infrastructure README. They are the operational policies that were assumed when Dependabot was configured: the version lag ceiling that prevents migrations from becoming security blockers, the auto-merge scope that keeps customer-facing formatting libraries under human review, the security SLA that matches the contractual obligations the company accumulated in its third year. Those are the decisions that accumulate interest as the dependency list grows, the enterprise contracts arrive, and the gap between the tooling's configured behavior and the team's assumed dependency maintenance posture widens invisibly until a CVSS 10.0 CVE, an auto-merged formatting regression, or a 47-day remediation timeline makes it visible. The new CTO onboarding problem is acute for dependency policy specifically: the incoming technical leader finds the .github/dependabot.yml file and knows the tooling, but cannot determine the version lag ceiling, the auto-merge scope, the security SLA, or whether any of those parameters match the enterprise customer contracts already signed. The dependency update policy ADR makes those parameters explicit, auditable, and findable without requiring a security incident to surface them. The WhyChose extractor finds the dependency management discussion in your AI session history — the conversation where your founding engineer chose the pinning model, the update cadence, and whether to enable automated PRs — and surfaces the commitments made in that session, so you can check which of the four policy elements were documented and which were left to accumulate interest.
The dependency update policy ADR: five sections
Section 1: Update cadence policy and version lag ceiling. Specify the update cadence for each category of dependency update: how frequently Dependabot or Renovate is configured to check for and open PRs on patch, minor, and major updates. Then specify the version lag ceiling: the maximum number of major versions the codebase is permitted to run behind the current stable release for any production dependency before a migration is required. A common threshold is two major versions — beyond which security backport coverage from most library maintainers expires. Document how the ceiling is monitored: whether a dependency audit is run on a regular cadence (npm outdated, pip list --outdated, bundle outdated) and who is responsible for tracking when a dependency crosses the ceiling threshold and opening the migration issue. Include the end-of-life policy: the maximum lag after a dependency's announced end-of-life date before a migration must be completed, and the process for tracking EOL announcements (checking endoflife.date for runtime dependencies, subscribing to maintainer mailing lists or release channels for critical production libraries). The lag ceiling is not a performance target — it is a safety constraint, and it should be treated as one in the ADR. A dependency that crosses the ceiling is not "due for an upgrade"; it is outside the policy boundary, and the migration issue must be created and prioritized regardless of sprint capacity.
Section 2: Automated tooling configuration and changelog review requirement. Specify the dependency classification that determines auto-merge eligibility: which categories of dependency update can be merged automatically when CI passes, and which categories require a human to read the changelog before merge. At minimum, two categories require explicit specification. Infrastructure-only dependencies — test runners, build tools, linters, type checkers, and dev dependencies with no production runtime surface — are generally safe to auto-merge on CI pass, because a behavioral change in a test runner or a code formatter does not affect customer-facing output. Production dependencies whose output appears in customer-facing responses — date and time formatting libraries, currency and number formatting libraries, serialization libraries, PDF or email generation libraries, HTTP client libraries that set headers visible to third parties — require changelog review before merge, because a patch-version behavioral change in these libraries can alter customer-visible output in ways that no existing test covers. Document the review process: who is responsible for the changelog review for flagged PRs, the maximum time a flagged PR can sit unreviewed before escalation, and the mechanism for blocking auto-merge on flagged PRs (typically CODEOWNERS assignment or a branch protection rule requiring a named reviewer). Also specify the auto-merge scope explicitly: whether the rule applies only to patch updates, to patch and minor updates, or to all updates below a specified threshold. Auto-merge on major updates is almost never appropriate and should be explicitly excluded if it is not intended.
Section 3: Security update SLA and CVE severity triage procedure. Specify the security update SLA per CVE severity level: the maximum number of calendar days from CVE publication to patched version deployed to production. Include the severity classification used (CVSS base score, vendor-assigned severity, or the team's own classification) and the SLA per level. Cross-reference any customer contract security addendums, SOC 2 control commitments, ISO 27001 control objectives, or security questionnaire responses that specify a vulnerability remediation timeline — the policy SLA must satisfy the most restrictive external commitment. Specify the triage procedure: the process by which a CVE is identified (security alert notification, Dependabot security alert, manual CVE monitoring), the process by which it is classified (who reviews it, what information they need, how quickly they must make the classification), and the prioritization track that activates when a security update SLA is in force (separate from the sprint backlog, with direct assignment to an engineer and a maximum-age alert if the SLA window is approaching). Document the exception process: what happens when a patched version is not yet available, when the patch requires crossing a major version migration that cannot be completed within the SLA window, or when the vulnerability requires a compensating control at the application layer while the patch is prepared. The exception process should not be left to individual engineering judgment at the moment of a CVE — it should be specified in the policy so that the team knows what to do before the CVE arrives.
Section 4: End-of-life dependency policy and migration trigger. Specify how the team tracks dependency end-of-life announcements for the runtime environment (Node.js, Python, Ruby, Java, Go), the framework (Express, Django, Rails, Spring), and critical production dependencies (database drivers, cryptography libraries, authentication libraries). Include the sources used to monitor EOL status and the cadence at which they are checked. Specify the migration trigger: the maximum lag after the announced end-of-life date before a migration must be completed and deployed to production. For runtimes and frameworks, a common policy is six months after the EOL announcement — long enough to plan and execute the migration without emergency pressure, short enough to avoid the period when security patches stop being published. For critical production libraries, a shorter window (three months) is appropriate because the security backport window typically closes at EOL. Document the relationship between the version lag ceiling and the EOL policy: when a dependency reaches EOL while the codebase is more than one major version behind, the EOL policy and the version lag ceiling both apply, and the team may need to complete multiple major version migrations in sequence to both satisfy the EOL policy and restore the codebase to within the lag ceiling. This scenario — deferred migrations converging with an EOL announcement — is the most operationally disruptive outcome of the update policy gap, and the ADR should specify how it is handled before it occurs.
Section 5: Breaking change detection and test coverage requirements. Specify the test coverage requirements that the dependency update policy implicitly assumes. Auto-merge on CI pass is only safe when the CI suite covers the behaviors that a patch or minor update to each auto-merge-eligible dependency could change. For infrastructure-only dependencies, CI coverage is generally sufficient. For production dependencies, CI coverage is the open question: the test suite covers the behaviors engineers wrote tests for, but it does not cover behaviors they did not test. Specify the requirement for production dependencies that produce customer-facing output: before a dependency is classified as auto-merge-eligible, the tests must cover at least the output format and boundary values of every customer-facing feature that uses the library. This requirement should be enforced prospectively — any new production dependency that produces customer-facing output requires test coverage of its output behavior before it can be added to the auto-merge eligible list. The API security decision record describes the input validation surface from the outside; the dependency update policy ADR describes the output behavioral surface from the inside — the set of library behaviors that customer-facing features rely on and that test coverage must exercise before automated updates can be trusted not to silently change what customers see. Document the process for updating the coverage requirement when new customer-facing features are built using existing auto-merge-eligible dependencies: a feature that introduces a new customer-visible use of a library's output format should trigger a test coverage review for that library before the feature ships, not after a patch version silently changes the format in production.
FAQ
What should a dependency update policy specify beyond the basic update cadence?
Four things: the version lag ceiling (the maximum major versions the codebase is permitted to run behind current stable before migration is required — two major versions is a common threshold that keeps the codebase within the security backport window); the security update SLA (maximum days per CVE severity from publication to patched version deployed, cross-referenced to the most restrictive customer contract commitment); the auto-merge eligibility classification (which dependency categories can be merged on CI pass and which require changelog review — infrastructure-only vs. production libraries with customer-facing output); and the end-of-life policy (the maximum lag after an EOL announcement before a migration is complete). The update cadence alone — "we run Dependabot weekly" — addresses none of these four requirements.
How should teams configure Dependabot or Renovate to avoid both PR queue accumulation and behavioral regression?
Separate update classes with different automation levels rather than applying a single auto-merge or manual-review policy uniformly. Security alerts: auto-create PR, assign outside sprint process, enforce maximum-age label escalation at the SLA boundary. Patch updates to infrastructure-only dependencies: auto-merge on CI pass, no changelog review. Patch updates to production libraries with customer-facing output: auto-create PR, require changelog review before merge, block auto-merge via CODEOWNERS or branch protection. Minor updates: changelog review and human approve before merge. Major updates: require migration issue, migration branch, and integration test coverage before the PR is opened. This classification can be encoded in Renovate's automerge and packageRules configuration; Dependabot requires branch protection rules and CODEOWNERS to enforce the review requirement for specific dependency categories.
What is the right security update SLA for critical CVEs and how does it connect to customer contracts?
Critical CVEs (CVSS 9.0–10.0): 7–14 days from publication to patched version deployed. High severity (CVSS 7.0–8.9): 30 days. Medium severity (CVSS 4.0–6.9): 90 days. These align with SOC 2 Type II audit expectations and most enterprise vendor security addendums. The customer contract connection: many enterprise security addendums specify 30 days for critical, which is actually the high-severity baseline — confirm which SLA appears in your contracts and set the policy SLA to the most restrictive external commitment. The engineering team must know which SLA the company has committed to, because the binding SLA is the contract, not the internal default. Document this cross-reference in the update policy ADR so it is findable without reviewing every signed customer contract at the moment a CVE arrives.
How does dependency debt accumulation create a security constraint rather than just a technical debt item?
Dependency debt becomes a security constraint when the security patch for a published CVE is only available in a major version the codebase cannot adopt without completing deferred migrations. Most library maintainers backport security patches for one minor version series beyond the current major release — not for versions two or three majors behind. A team running three major versions behind on a library that processes external input has no patch available for a CVE and must choose between completing a multi-week migration under emergency conditions, implementing an incomplete application-layer workaround, or accepting the exposure. None of these are good outcomes. The transition from technical debt to security constraint happens at the moment a CVE is published against a version no longer receiving security backports — which is directly determined by how far the version lag has been allowed to accumulate. A version lag ceiling prevents this transition by keeping the codebase within the window where patches are available.