The vendor dependency governance decision record: why the third-party dependency model you chose determines your supply chain risk surface and your vendor lock-in accumulation rate
Vendor dependency governance is not a security checklist item that compliance teams review once per year and engineers ignore between audits. It is a set of founding decisions that most engineering teams make implicitly, incrementally, and without aggregate visibility — what criteria a new package must meet before an engineer can add it to the codebase, who is the named owner of each external integration, at what point a vendor's API surface becomes large enough that direct calls without an abstraction layer constitute an architectural risk rather than a pragmatic shortcut, how often existing dependencies are reviewed against active maintenance and current security standards, and what concentration limits prevent any single vendor from accumulating so many integration points that the migration cost of a pricing change or a product discontinuation becomes an existential engineering project rather than a planned quarter of work. These decisions together determine two structural properties that are invisible in sprint velocity charts and quarterly engineering reviews but visible in the post-mortems of forced emergency migrations, in the findings of software supply chain security audits, and in the technical due diligence reports of acquisitions that never close at the originally expected price: the supply chain risk surface, which is the probability that a single external dependency failure propagates to a production incident or a forced migration, and which is set by whether the dependency intake model requires security evaluation, whether every dependency has a named owner with explicit responsibility for vulnerability monitoring, and whether the CI/CD pipeline enforces integrity verification that catches a compromised package before it reaches a production build; and the vendor lock-in accumulation rate, which is the rate at which vendor-proprietary API calls, proprietary data models, and infrastructure primitives without portable equivalents enter the codebase per quarter without tracked offsetting abstraction, and which is set not by the individual quality of each integration decision but by whether abstraction requirements are specified at the point of the integration decision rather than treated as a future refactor that is perpetually deferred when the team is shipping under deadline pressure.
A 31-person healthcare scheduling SaaS built a patient appointment management platform for outpatient clinic networks. The platform coordinated scheduling between clinics, patients, and referring physicians, and relied on three external integrations that were central to its product functionality: DocuSign for patient consent form collection, Stripe for co-pay processing, and Twilio for appointment reminder SMS. Each integration had been built by different engineers at different points in the company's history — the DocuSign integration by the founding CTO in year one, the Stripe integration by a senior engineer hired in month 8 who had left the company 14 months later, and the Twilio integration by a contract developer engaged for a specific clinic onboarding project who had built the integration into four separate clinic-specific notification flows. The company had no dependency registry that listed its external integrations, no named owner for any of them, and no documentation of which code paths called which external APIs.
In February, DocuSign announced the deprecation of their legacy eSignature v2 API with a 90-day sunset window. The announcement was sent to the email address on the DocuSign account, which was the founding CTO's personal email — the CTO had left the company eighteen months earlier, and nobody had transferred account ownership to a current team member. The engineering team learned about the deprecation not from DocuSign's announcement but from a customer who mentioned it on a support call after receiving an email from DocuSign directly advising customers to migrate their integrations. By the time the engineering team received the information, 34 days of the 90-day window had already elapsed.
The engineering team's first task was to understand the scope of the migration: how many code paths called the v2 API, what request parameters were being used, and whether any of the integrations relied on v2-specific response fields that had been removed in v3. The codebase had grown over four years without consistent patterns — the DocuSign integration was not encapsulated behind a service layer or an interface; API calls were scattered across the application code in the consent form workflow, the onboarding flow, the referral processing system, and three separate clinic-specific customization branches that had been merged into the main application over time. A four-day codebase audit by two engineers identified 14 separate code paths containing DocuSign API calls, using 7 different request structures and 4 different response parsing patterns, some of which relied on fields that had been removed in v3 and replaced with new equivalents. The migration required rewriting each of the 14 call sites, building a unified client wrapper around the v3 API, writing a test harness that verified each workflow against the DocuSign sandbox environment, and running a coordinated deployment with a brief maintenance window to prevent any patient consent form submissions from being lost during the cutover. The total engineering investment was eight weeks of work by two engineers — work that consumed the entire Q2 roadmap commitment the company had made to its enterprise clinic customers and that required a CFO-level conversation about the customer commitments that would not be met. Connect this to the build-vs-buy decision record: the build-vs-buy decision is where vendor dependency governance begins; a build-vs-buy process that evaluates the vendor's integration surface, its API stability history, and its deprecation policy as part of the "buy" evaluation will surface the governance requirements — ownership assignment, abstraction layer design, registry entry creation — at the point when the integration decision is being made, when specifying those governance requirements adds a few hours to the planning process; a build-vs-buy process that evaluates only cost, feature coverage, and implementation time will leave those governance requirements unspecified, and the cost of the unspecified governance work will be paid later — not as a planned quarter but as an emergency migration when the vendor's deprecation clock has already started running without the engineering team's knowledge because the account owner is someone who left the company 18 months ago.
A 44-person data pipeline company built a real-time event processing and enrichment platform — a service that ingested application events from customer codebases, applied a series of transformation and enrichment steps, and forwarded the processed events to downstream storage and analytics destinations. The platform's core pipeline was built in Node.js and over two years of active development had accumulated 847 direct and transitive npm packages, across a monorepo containing four services. The company had no policy governing the addition of new dependencies. Engineers could run npm install at will. There was no required review process for new packages, no ownership assignment, and no regular audit of the existing dependency inventory. The security team — one part-time security engineer shared with three other products in the company — had automated CVE scanning via a SaaS security tool, but the scanning tool flagged vulnerabilities in dependencies only; it did not evaluate maintainer status, package provenance, or download pattern anomalies that might indicate a compromised package.
In April, a security researcher published a disclosure that a widely-used cryptographic utility package — a small, apparently well-maintained helper for HMAC computation that had been in production use by thousands of Node.js applications — had been quietly transferred to a new maintainer six months earlier following the original maintainer's announced retirement. The new maintainer had published three patch-version releases over the following months that appeared to be routine updates. The third of those releases had contained a backdoor in the HMAC implementation that exfiltrated computed keys to an external endpoint under specific triggering conditions. The malicious code was obfuscated in a minified bundle and was not immediately visible in the published source diff. The original package had 4.7 million weekly downloads. The compromised version had been in production on the company's platform for 34 days before the disclosure.
The company's security engineer identified the compromised package within two hours of the public disclosure, using the CVE feed from the security tool. The package was pinned to a specific version in three of the four services. In the fourth service, it was a transitive dependency of an analytics utility package, and was not pinned separately — the dependency had been added 14 months earlier by an engineer who had subsequently left the company, and the service that contained it had been maintained by a rotating set of engineers who knew what the service did but had not reviewed its dependency tree. The immediate remediation — upgrading the three directly-pinned services and force-updating the transitive dependency in the fourth — was completed within six hours. The harder question was the exposure assessment: for 34 days, the platform had processed customer events that included authentication tokens, API keys, and session identifiers as part of enrichment pipelines. The security engineer needed to determine whether any of those values had been computed as HMAC inputs under the triggering conditions of the backdoor. That analysis required reconstructing 34 days of event payloads from the company's pipeline logs, identifying which payloads had triggered HMAC computation in the compromised package, and determining whether the external exfiltration endpoint had been reachable from the company's network. The analysis took four engineers three days to complete. The conclusion was that the triggering conditions had not been met in the company's specific usage pattern, but the company had to notify seven enterprise customers of the 34-day exposure window and commission a third-party forensic review to support the "no confirmed exfiltration" determination — a process that cost approximately $40,000 and consumed six weeks of engineering management time in customer calls and documentation requests. Connect this to the CI/CD pipeline security decision record: the CI/CD pipeline security model is the enforcement layer for dependency intake governance; a pipeline that verifies published package integrity against the cryptographic hash recorded in the lock file at the time of first addition will detect a re-published package with modified contents at build time rather than 34 days into a production deployment; a pipeline that rebuilds the lock file from the package registry on each build run is not performing integrity verification — it is re-resolving the dependency tree and accepting whatever the registry returns, which is exactly the trust model that supply chain attacks exploit; the integration between the dependency intake governance model and the CI/CD security model is that the governance model specifies which packages are acceptable at intake time and assigns ownership responsibility, while the pipeline security model verifies at build time that the packages delivered by the registry match the packages that were evaluated at intake time; without both layers, the governance model's evaluation work at intake time is rendered ineffective by the absence of continuous integrity enforcement downstream.
A 59-person enterprise SaaS company built a B2B workflow automation platform for operations and finance teams at mid-market companies. The platform had grown from a simple integration hub to a full-featured automation engine over four years, and its infrastructure had evolved through the decisions of three consecutive CTOs and a series of engineers with varying infrastructure philosophies. The company ran entirely on AWS. The first CTO had chosen AWS Lambda and DynamoDB for the initial version of the platform because the serverless model reduced operational overhead for a small team and DynamoDB's autoscaling matched the spiky, unpredictable load profile of a new SaaS product. The second CTO had extended the architecture with Kinesis Data Streams for the event ingestion layer because Kinesis integrated natively with Lambda and eliminated the need to operate a Kafka cluster, and with SQS and SNS for the notification and async processing layer because the team was already familiar with those services. The third CTO, hired to scale the engineering team, had added AWS Step Functions for the complex multi-step workflow orchestration that the product's enterprise tier required, AWS Cognito for the identity and access management layer that would support SSO and enterprise authentication requirements, and Lambda@Edge for the geographic performance optimization that the enterprise sales team had identified as a requirement for EU customers.
None of these decisions were wrong in isolation. Each one solved a real problem at the time it was made, with a team that had limited capacity and could not afford to operate the open-source equivalents. But the decisions were never aggregated into a vendor concentration picture. No one had ever counted how many of the platform's core architectural components relied on AWS-proprietary features with no portable equivalents: Kinesis consumer groups with no Kafka equivalent in the Lambda invocation model, DynamoDB's conditional expression syntax with no standard SQL translation, Step Functions' state machine definition language with no cross-platform equivalent, Cognito's custom authentication flows with no drop-in OIDC replacement. The company's infrastructure costs had also grown steadily — not dramatically, but at a rate that the finance team noticed but attributed to growth rather than to pricing model changes in the underlying services.
In the spring, the company received an acquisition inquiry from a private equity firm focused on enterprise software. The PE firm's technical due diligence team spent three weeks reviewing the architecture with three of the company's engineers. One of the diligence team's deliverables was a "platform portability assessment" — an estimate of the engineering investment required to re-platform the product on a different cloud provider or on a multi-cloud architecture. The assessment concluded that 16 of the platform's 21 core services contained direct AWS SDK calls for proprietary services with no abstraction layer, that the DynamoDB data model used 14 conditional expression patterns that had no direct translation to any open-source database, and that the Step Functions workflow definitions were embedded directly in the application code rather than in a workflow definition abstraction that could be compiled to a different orchestration engine. The re-platforming estimate was 18 to 24 months of engineering time, assuming a team of 8 engineers, with no new feature development possible during the migration. The PE firm's offer, which had initially valued the company at $34 million based on revenue multiples, was revised downward by $3.74 million — an 11% reduction — citing infrastructure concentration risk and the operational leverage implications of being committed to a single vendor's pricing model for a product whose gross margins had already been under pressure from AWS cost growth. The engineering team had not made a decision to be AWS-dependent in any meaningful sense; they had made 23 individually reasonable integration decisions over four years that had collectively produced a concentration profile that reduced the company's acquisition price by $3.74 million. Connect this to the technical debt decision record: vendor lock-in accumulation is a form of architectural technical debt, and it shares the defining characteristic of all technical debt — it is invisible in the metrics the engineering team uses to evaluate its own health (velocity, deployment frequency, incident rate) while accumulating at a rate determined by the team's integration decisions; the technical debt decision record specifies how technical debt is tracked, evaluated, and prioritized against new feature work; a technical debt tracking model that does not include vendor concentration as a debt category will not surface the accumulation until a forcing function — an acquisition, a pricing change, a vendor deprecation — makes it visible in a context where the cost of addressing it is dramatically higher than the cost of addressing it incrementally; the practical mechanism for catching vendor lock-in accumulation before it produces a concentrated risk profile is a quarterly vendor concentration review that aggregates the abstraction layer status column from the dependency inventory and produces a per-vendor migration cost estimate, so that the picture the PE firm's diligence team constructed in three weeks is instead something the engineering team has on a single page updated every quarter.
Structural properties set by the vendor dependency governance decision
Two structural properties are determined by the founding decisions about dependency intake, ownership assignment, abstraction requirements, and vendor concentration tracking. Neither is visible in the engineering metrics that most teams monitor — sprint velocity, deployment frequency, DORA metrics, code coverage — because both properties are determined not by the quality of individual engineering execution but by the governance structure around how external dependencies are evaluated and tracked. Both become visible in supply chain security incident post-mortems, in the engineering time consumed by emergency API migrations, and in the technical sections of acquisition due diligence reports where the concentration of vendor-proprietary integrations appears as a dollar figure rather than as an architectural diagram.
Property 1: Supply chain risk surface and the dependency intake gap. The supply chain risk surface is the probability that a single external dependency failure — a package compromise, a maintainer abandonment that leaves a critical vulnerability unpatched, a vendor API deprecation with a short sunset window, a package registry typosquatting attack, a dependency whose sole maintainer transfers ownership to a malicious actor — propagates to a production incident affecting customers or to a forced emergency migration that consumes the engineering team's capacity for a quarter. The surface is not determined by the number of dependencies the codebase contains — a codebase with 2,000 dependencies under active governance has a smaller supply chain risk surface than a codebase with 200 dependencies without it — but by two specific governance gaps. The first gap is the absence of a named owner for each dependency: when a package has no named owner, the owner relationship is implicitly distributed across whichever engineers happen to be working in the area of the codebase where the package is used, which means that when the package's maintainer abandons the project, transfers ownership, or publishes a malicious update, no specific person receives the signal and no specific person is responsible for evaluating the risk and acting. The second gap is the absence of integrity verification in the CI/CD pipeline: when the build system re-resolves dependencies from the package registry on each build run rather than verifying the resolved packages against cryptographic hashes recorded at intake time, the build trusts whatever the registry serves, which is exactly the attack surface that package compromise exploits. The supply chain risk surface is measurable as the fraction of dependencies in the inventory with a named owner, a verified maintenance status from the last 90 days, and a pinned version with integrity hash in the lock file. A team that can produce that fraction for its full dependency inventory has a bounded, visible surface; a team that cannot produce it has an unbounded surface whose exposure is unknown until an incident reveals it. The measurement requires only two things: a dependency inventory that is maintained as a living document, and a CI/CD security configuration that enables integrity verification mode. The engineering investment in both is measured in days, not weeks; the cost of not having them is measured in the incident response and migration time that the three case studies above consumed.
Property 2: Vendor lock-in accumulation rate and the abstraction decision gap. The vendor lock-in accumulation rate is the rate at which vendor-proprietary API calls, proprietary data formats, proprietary infrastructure primitives, and vendor-specific configuration schemas enter the codebase per quarter without tracked offsetting abstraction. It is distinct from vendor usage — a company can use a vendor heavily without accumulating lock-in if its integrations are built behind abstraction layers that isolate vendor-specific implementation details from the application logic that depends on the integration's behavior. The accumulation rate is determined by a single architectural decision point: the build-vs-buy and integration planning discussion. When that discussion includes the question "if we need to replace this vendor in 18 months, what is the migration cost, and do we need an abstraction layer to make that cost acceptable?" the answer drives either the abstraction design decision or the explicit acceptance of the lock-in with a documented migration cost estimate. When that discussion does not include the question — when it evaluates only feature coverage, implementation time, and cost — the abstraction decision defaults to "no abstraction required" by omission, and the integration is built directly, adding to the lock-in accumulation without anyone having decided that the accumulation is acceptable. The critical characteristic of the accumulation rate failure is that it is produced by individually reasonable decisions. No engineer who chose AWS Step Functions for workflow orchestration, AWS Cognito for enterprise authentication, and Kinesis for event ingestion made a bad decision — each choice solved a real problem efficiently given the team's constraints at the time. The failure is the absence of an aggregation mechanism: a quarterly vendor concentration review that maps the inventory to a per-vendor migration cost estimate and flags when any single vendor's total migration cost has crossed a defined threshold. At the threshold, the team is not required to immediately re-platform — they are required to make an explicit decision about whether the concentration is acceptable given the current vendor risk profile, the current pricing trajectory, and the current business context. The teams that produce the $3.74 million acquisition price reduction are teams that have never crossed the threshold because they have never measured it; the accumulation has been invisible in the engineering health metrics they actually track, and it surfaces only in a context — an acquisition, a vendor pricing crisis — where addressing it is no longer an engineering architecture decision but a negotiating position. Connect this to the build-vs-buy decision record: the build-vs-buy decision is the natural home for the abstraction layer requirement question; a build-vs-buy template that includes vendor tiering, migration cost estimation, and abstraction layer recommendation as standard evaluation sections ensures that the concentration tracking work happens at the moment when the integration is being designed, not three years later when the dependency inventory needs to be reconstructed from a codebase audit to answer a due diligence question.
The vendor dependency governance ADR: five sections
Section 1: The dependency intake governance model. The dependency intake governance model section specifies the evaluation criteria that a new external dependency — OSS package or SaaS integration — must meet before it is added to the codebase, the exception process for dependencies that do not meet all criteria, and the ownership assignment requirement at the point of addition. Four criteria apply to OSS packages. Active maintenance: the package has had a substantive commit from a named maintainer within the last 12 months; the maintainer maintains a public identity with recent activity that enables verification of package publish authenticity; the package's issue tracker shows active engagement with reported security disclosures. Security posture: the package has no unpatched CVEs with CVSS score 7.0 or above in the version being added; the published package is pinned to an exact version in the lock file with a cryptographic integrity hash at the time of addition; the package uses semantic versioning consistently. Scope justification: the functionality the package provides cannot be replicated in under 200 lines of code without meaningfully increasing risk or error surface; the package operates in a domain where the package maintainer has domain expertise that the adding engineer should not attempt to replicate; the transitive dependency footprint of the package is proportional to the functionality it provides. Ownership assignment: a named engineer on the current team is assigned as the dependency owner in the dependency registry at the time of addition, with explicit acknowledgment that the owner is responsible for monitoring security advisories, evaluating major version upgrades, and initiating removal if the package becomes unmaintained. For SaaS API integrations, the criteria parallel the OSS criteria but address commercial rather than technical risk: the vendor has been operating for at least 24 months; the vendor's terms of service include an API stability commitment or a minimum deprecation notice period; the vendor provides a data export mechanism in a non-proprietary format; the vendor tiering assessment (see section 3) has been completed and the abstraction layer requirement determination has been documented. The exception process allows dependencies that fail one or more criteria to be added with tech lead approval if the engineer documents the specific exception, the business justification, and the compensating controls applied. Exceptions are tracked in the dependency registry alongside standard entries, marked as exceptions, and reviewed at each quarterly dependency review to determine whether the compensating controls remain adequate or whether the dependency should be removed. Connect this to the build-vs-buy decision record: the build-vs-buy decision record is the document that captures the evaluation of vendor integrations against the intake criteria and the abstraction layer determination; the dependency governance ADR specifies the criteria; the build-vs-buy record for each specific integration applies the criteria to the specific vendor and documents the decisions, exceptions, and accepted tradeoffs; without the build-vs-buy record as the per-integration implementation document, the governance model's criteria exist in the ADR but are not applied in practice — engineers making integration decisions may be unaware of the ADR or may skip the evaluation step because there is no artifact that makes the evaluation visible in the pull request review process; the build-vs-buy record, attached to the PR that first introduces the integration, is the enforcement mechanism that makes the governance criteria applicable.
Section 2: The dependency inventory and ownership registry. The dependency inventory section specifies the structure of the registry, the named owner who maintains it, the review cadence, and the fields that each entry must contain. The registry is a maintained document — a markdown table, a CSV file tracked in git, or a structured record in the team's documentation system — not a generated artifact from the package manager. Package manager lock files and manifests are the authoritative source for what packages are present in the codebase; the dependency inventory is the authoritative source for ownership, review history, and migration complexity, which the lock file cannot provide. Each registry entry for a direct dependency contains eight fields: the dependency name and current pinned version; the dependency type (OSS library, SaaS API integration, infrastructure service, data service, authentication service); the named owner on the current engineering team and the date of ownership assignment; the date of the last governance review for this entry; the current maintenance status (active, stale-less-than-24-months-no-release, abandoned-no-response-to-issues, deprecated-vendor-announced, end-of-life); the abstraction layer status (direct integration, interface-wrapped, fully abstracted with portability tests); the migration complexity estimate using a three-tier scale (low: under one engineer-week; medium: one to four engineer-weeks; high: over one engineer-month); and the exception status (standard: meets all intake criteria; exception: approved by tech lead with documented rationale, date of approval, and compensating controls). The registry owner — a named engineer, typically the tech lead or the senior engineer designated as platform owner — is responsible for keeping the registry current with each integration PR that adds or removes a dependency, conducting quarterly reviews of the full registry, and flagging entries whose maintenance status has changed since the last review. The quarterly review passes each entry through four questions: is the current maintenance status still accurate? has the version been updated to incorporate security patches since the last review? is the current owner still on the team? has the migration complexity estimate changed as the integration has deepened? Entries that fail the maintenance status check — packages where the last commit has aged past 12 months, or where a vendor deprecation announcement has arrived — are flagged for a removal or migration decision at the quarterly review rather than at the point when a security vulnerability is discovered or a deprecation deadline arrives. Connect this to the dependency update policy decision record: the dependency update policy specifies how and how quickly security vulnerabilities in existing dependencies are patched; the dependency inventory provides the named owner who is responsible for executing the patch; without named ownership, the dependency update policy's SLA timelines for critical CVE remediation depend on the engineering team collectively noticing that a CVE affects a dependency they collectively own, which is a diffuse responsibility that produces the predictable failure mode where a high-severity CVE ages past its remediation SLA in a package with no named owner because each engineer who saw the alert assumed that the engineer who added the package was handling it.
Section 3: Vendor tiering and concentration policy. The vendor tiering section specifies how external vendors are classified by migration cost and operational criticality, the concentration limits that apply per vendor tier, and the abstraction layer requirements by tier. Tier 1 vendors are those where the total engineering investment to replace the vendor's integration, estimated in the dependency inventory, exceeds four engineer-weeks, or where the vendor's service is in the critical path of the product's core value proposition such that a vendor outage produces a product outage. Tier 2 vendors are those where the migration cost is under four engineer-weeks and where the vendor's service is not in the critical path — removing it degrades a feature but does not prevent the product's primary workflow from functioning. The concentration policy specifies two limits. Per-vendor concentration: no single vendor's Tier 1 integrations may collectively represent a migration cost estimate exceeding 12 engineer-months without a documented exception approved by the CTO or engineering VP, with a quarterly review of whether the exception's business justification still applies. Per-category concentration: no single category of infrastructure service — message queueing, event streaming, workflow orchestration, authentication and identity, object storage — may be supplied by a single vendor's proprietary implementation without an abstraction layer or a documented migration plan, unless a category concentration exception has been approved. The category concentration limit addresses the pattern in the third case study: no single AWS proprietary service represented an excessive migration cost, but the accumulation across all infrastructure categories produced a total re-platforming estimate of 18-24 months; the category concentration policy catches accumulation within categories before it crosses into the total concentration profile that appears in acquisition due diligence. The concentration review happens quarterly, using the migration complexity estimates from the dependency inventory, producing a per-vendor and per-category concentration summary that the tech lead and CTO review together. When a vendor's concentration crosses the defined threshold, the review produces one of three documented outcomes: the concentration is accepted with a documented rationale and a migration plan that is updated at each subsequent quarterly review; the team begins a planned migration to reduce the concentration, with milestones tracked in the backlog; or an abstraction layer is added to the existing integrations to reduce the migration cost estimate and bring the concentration below the threshold. Connect this to the technical debt decision record: vendor concentration that exceeds the defined policy limit is a specific category of technical debt — one that may have been incurred through individually reasonable decisions — and the same tracking and prioritization framework that applies to other technical debt categories applies to vendor concentration debt; the technical debt decision record specifies how debt is registered, estimated, and prioritized against feature work; vendor concentration debt belongs in the same registry, with the migration cost estimate as its debt principal, so that the prioritization conversation about whether to run the quarterly vendor concentration review or to ship a customer-requested feature happens with explicit visibility into both the debt cost and the feature cost, rather than with the debt being invisible until an acquisition diligence team makes it visible in the form of a reduced offer price.
Section 4: Abstraction layer requirement policy. The abstraction layer requirement policy specifies the four conditions under which a vendor integration requires an abstraction layer before the integration is built, the form that the abstraction layer takes for different integration types, the test format that verifies portability, and how the requirement is documented at build-vs-buy or integration planning time. Condition 1: The vendor's API is called from more than three separate code paths or services. At that threshold, a vendor API change requires coordinated updates across multiple modules, and an abstraction layer localizes the change to a single implementation. Condition 2: The integration involves a data persistence or transport mechanism that uses a vendor-proprietary format, query language, or protocol with no standard equivalent. DynamoDB conditional expressions, proprietary workflow state machine languages, vendor-specific message queue acknowledgment models, and custom authentication flow schemas all require abstraction layers because the migration cost scales with the number of call sites rather than with the size of the abstraction. Condition 3: The vendor has no published API stability guarantee, no contractual deprecation notice period, or no data portability mechanism in their terms of service. Integrations built directly on best-effort or unguaranteed vendor APIs require abstraction layers to contain the blast radius of unannounced changes. Condition 4: The migration complexity estimate for replacing the integration exceeds two engineer-weeks. The abstraction investment is typically 20-30% of the integration implementation cost; if the migration cost without abstraction exceeds two engineer-weeks, the abstraction investment produces positive expected value by reducing the migration cost to one to two engineer-weeks and by enabling incremental migration without a complete feature freeze. The abstraction form by integration type: for SaaS API integrations, a service interface that isolates the vendor-specific request and response model from the application code that calls it — the application code calls the interface, the concrete implementation calls the vendor API, and a portability test verifies that a mock implementation of the interface produces the same application behavior as the real implementation; for infrastructure services, an adapter pattern that wraps the vendor-specific client with a generic interface matching the service category — a queue interface for message queuing services, a workflow engine interface for orchestration services — with the same portability test requirement; for data storage integrations, a repository pattern that isolates the vendor-specific query language from the domain model operations the application requires. The abstraction layer requirement is documented in the build-vs-buy record or the integration planning document, not in a separate technical design document, so that the requirement is visible in the PR review process at the time the integration is first introduced. The abstraction layer is not a migration guarantee — a well-designed abstraction layer for a complex integration can still require significant work to connect to a new backend — but it is a migration cost containment mechanism that converts an "18 to 24 month re-platform" estimate into a "4 to 8 week per-service migration" estimate by ensuring that the vendor-specific code is localized and that the migration path can be executed one service at a time rather than requiring a coordinated cutover of the full application. Connect this to the CI/CD pipeline security decision record: the abstraction layer is not only a lock-in mitigation — it is also a supply chain security mechanism; an integration built behind an abstraction layer can have its underlying vendor implementation replaced in a single code change when a vendor library is compromised, rather than requiring changes across 14 separate code paths under incident response pressure; the CI/CD pipeline security model enforces integrity verification of the concrete implementation, while the abstraction layer ensures that the scope of a required replacement is bounded and executable within hours rather than weeks.
Section 5: Dependency review cadence and sunset policy. The dependency review cadence section specifies the regular review schedule, the criteria that trigger an out-of-cycle immediate review, the process for removing a dependency whose owner has left the company, and the migration lead time standard for deprecated dependencies. The regular review cadence is quarterly: the dependency registry owner reviews all entries in the full inventory, updates maintenance status from current registry and vendor information, identifies entries whose migration complexity estimate has changed due to new integration work, reassigns ownership for entries whose named owner has left or changed roles, and flags entries that meet sunset criteria for a removal or migration decision. The quarterly review produces a written summary — a short document appended to the dependency inventory or posted to the engineering channel — that lists: entries with changed maintenance status, entries reassigned to new owners, entries flagged for sunset with the proposed timeline, and the per-vendor and per-category concentration summary from section 3. Out-of-cycle reviews are triggered immediately by: a CVE advisory affecting a package in the inventory (the named owner evaluates and patches within the timeframe specified in the dependency update policy); a vendor deprecation or end-of-life announcement for a Tier 1 integration (the engineering team is notified within 24 hours of the registry owner learning of the announcement, and a migration plan is drafted within one week); a public disclosure of a supply chain attack affecting a package ecosystem the team uses (the registry owner audits all packages from that ecosystem within 48 hours for similar vulnerability patterns); or a named dependency owner leaving the company (ownership is reassigned before the owner's last day — the offboarding checklist includes a dependency ownership transfer step). The sunset policy specifies the process for removing a dependency that has become unmaintained, deprecated, or replaced by in-house functionality. Three conditions trigger a sunset: the dependency's maintenance status has been "stale" (no commits in 12 months) for two consecutive quarterly reviews; the vendor has announced end-of-life with a specific sunset date; or the dependency's functionality has been replicated in-house as a side effect of other engineering work and the external package is no longer needed. The migration lead time standard for Tier 1 dependencies is 90 days from the sunset trigger to code removal — enough time to design the replacement, implement it, test it, and deploy it in the normal release cadence without emergency pressure. For Tier 2 dependencies, the migration lead time is 60 days. When a vendor announces a deprecation with less than the minimum lead time, the engineering team immediately escalates to the CTO or engineering VP to assess whether the migration can be executed within the announced window or whether the team needs to request an extension or evaluate a temporary workaround. The lead time standards exist so that when a vendor announces a 90-day deprecation window, the engineering team's response is "start the planned migration process" rather than "reconstruct the scope of the integration through a codebase audit" — which is only possible if the dependency inventory already contains the scope information and the abstraction layer (where required) has already localized the migration to a defined code boundary. Connect this to the open-source extractor: the vendor dependency governance decisions — why the dependency intake criteria were set at 12 months of active maintenance rather than 6, why the concentration threshold for a single vendor was set at 12 engineer-months and what alternatives were considered, why the abstraction layer requirement was triggered at the two-engineer-week migration threshold rather than a higher one, what the specific exception conditions were that allowed the early-stage DynamoDB integration to proceed without an abstraction layer and what the reasoning was behind that exception, why the quarterly review cadence was preferred over a continuous monitoring approach and what the decision was about which signals warranted immediate out-of-cycle review — are made in conversations: a CTO and a senior engineer debating whether a new vendor integration requires an abstraction layer before it is built; an engineering manager and a security engineer reviewing the dependency inventory after a supply chain disclosure and discovering that three packages in the inventory have no named owner; a VP Engineering and a CTO discussing whether the vendor concentration revealed by the previous quarter's review warrants an immediate investment in abstraction layers or can be deferred to the following quarter given a tight product roadmap; the written output is the dependency governance ADR, the dependency registry, and the abstraction layer designs; the reasoning behind those decisions — why the team accepted the lock-in at a specific point, what the alternatives that were rejected were and why they were rejected, what the specific conditions under which the team would revisit the abstraction question were — lives in the conversation history that preceded the written documentation, and that is exactly what WhyChose's extractor recovers from AI chat export history and makes findable when the new engineering manager needs to understand not just what the current governance model says but why specific thresholds and criteria were chosen and whether the original conditions that justified them still hold given changes in the team's size, the product's complexity, and the vendor landscape that has evolved since those decisions were made.
FAQ
What criteria should a dependency intake model require before a new package is added?
A dependency intake model should evaluate four criteria before a new package is added. Active maintenance: the package has had a substantive commit from a named maintainer within the last 12 months, the maintainer maintains a public identity that enables verification of package publish authenticity, and the issue tracker shows active engagement with security disclosures. Security posture: no unpatched CVEs with CVSS score 7.0 or above, an exact version pinned in the lock file with a cryptographic integrity hash at the time of addition, and consistent semantic versioning. Scope justification: the functionality cannot be replicated in under 200 lines of code without meaningfully increasing risk, the package operates in a domain requiring genuine expertise, and the transitive dependency footprint is proportional to the functionality provided. Ownership assignment: a named engineer is designated as the dependency owner in the dependency registry at the time of addition, with explicit responsibility for security advisory monitoring, major version upgrade evaluation, and removal if the package becomes unmaintained. Packages that fail one or more criteria may be added through an exception process with tech lead approval and documented compensating controls, tracked as exceptions in the registry and reviewed quarterly to verify that the exception remains justified.
When should a vendor integration require an abstraction layer?
Four conditions trigger a mandatory abstraction layer requirement. First, the vendor's API is called from more than three separate code paths or services — at that threshold, a vendor change requires coordinated updates across multiple modules and an abstraction layer localizes the change to a single implementation. Second, the integration involves a vendor-proprietary data format, query language, or protocol with no standard equivalent — the migration cost scales with call sites, not with interface complexity, so the abstraction investment has positive expected value at almost any scale. Third, the vendor has no published API stability guarantee or contractual deprecation notice period in their terms of service — integrations on unguaranteed surfaces require abstraction to contain the blast radius of unannounced changes. Fourth, the migration complexity estimate for replacing the integration exceeds two engineer-weeks — the abstraction investment, typically 20-30% of the integration implementation cost, produces positive expected value when the migration cost without abstraction exceeds two engineer-weeks. The abstraction requirement is documented in the build-vs-buy or integration planning record at the time the integration is being designed, not deferred to a future refactoring session, because the cost of adding abstraction before the integration is built is proportional to the interface complexity, while the cost after is proportional to the number of call sites, the data migration complexity, and the testing surface required to verify behavioral equivalence.
How should a dependency inventory and ownership registry be structured?
The dependency inventory is a maintained document — not a generated package manifest — covering direct external dependencies with eight fields per entry: dependency name and current pinned version; dependency type (OSS library, SaaS API, infrastructure service, data service, authentication service); named owner and ownership assignment date; date of last governance review; current maintenance status (active, stale, abandoned, deprecated-by-vendor, end-of-life); abstraction layer status (direct integration, interface-wrapped, fully abstracted with portability tests); migration complexity estimate (low: under one engineer-week; medium: one to four engineer-weeks; high: over one engineer-month); and exception status (standard or exception with approval date and compensating controls). Transitive dependencies are not individually tracked — automated security tooling provides better coverage of that surface. The inventory is reviewed quarterly by a named registry owner who updates maintenance status, reassigns ownership for entries whose owner has left, and flags entries meeting sunset criteria. The quarterly review produces a written summary covering changed maintenance statuses, reassigned ownership, sunset candidates, and the per-vendor concentration summary. The inventory's value is ownership clarity and migration cost visibility: when a deprecation notice arrives, the inventory answers within seconds who is responsible and what the rough engineering investment will be; when an acquirer's diligence team requests a vendor concentration analysis, the inventory produces the answer from the abstraction layer status and migration complexity columns without requiring a codebase audit.
What should a vendor dependency governance decision record specify?
Five specifications. First, the dependency intake governance model: the four evaluation criteria a new dependency must meet, the exception process with tech lead approval, and the ownership assignment requirement at the point of addition. Second, the dependency inventory and ownership registry: the eight-field structure, the named registry owner, the quarterly review cadence, and the distinction between the inventory (maintained document with ownership and migration complexity) and the lock file (generated artifact for version pinning and integrity). Third, the vendor tiering and concentration policy: Tier 1 vs Tier 2 classification by migration cost and criticality, the per-vendor 12-engineer-month concentration threshold, the per-category concentration limit requiring abstraction or a documented migration plan, and the quarterly concentration review process. Fourth, the abstraction layer requirement policy: the four triggering conditions, the abstraction form by integration type (service interface, adapter pattern, repository pattern), the portability test requirement, and the requirement to document the abstraction decision in the build-vs-buy or integration planning record at design time. Fifth, the dependency review cadence and sunset policy: quarterly regular review, immediate out-of-cycle review triggers (CVE advisory, vendor deprecation announcement, supply chain attack disclosure, named owner departure), the three sunset-triggering conditions, and the 90-day migration lead time standard for Tier 1 dependencies.
Further reading
- Build-vs-buy decision record — the build-vs-buy decision is where vendor dependency governance is first activated; a build-vs-buy evaluation that includes the vendor tiering assessment, the abstraction layer requirement determination, and the dependency registry entry creation as standard steps ensures that governance work happens at the moment when the integration is being designed; a build-vs-buy process that evaluates only cost, feature coverage, and implementation timeline creates a governance gap that manifests as emergency migration debt when the vendor's deprecation clock starts running without the engineering team's awareness because the account owner email address belongs to someone who left the company 18 months ago.
- Technical debt decision record — vendor lock-in accumulation is a category of architectural technical debt that shares the defining characteristic of all technical debt: it is invisible in the engineering health metrics the team monitors while accumulating at a rate determined by integration decisions; a technical debt tracking framework that does not include vendor concentration as a debt category will not surface the accumulation until a forcing function makes the total cost visible in a context — an acquisition, a vendor pricing crisis, a product discontinuation — where addressing it is a negotiating position rather than an engineering architecture decision; the practical mechanism is a quarterly vendor concentration review that produces a per-vendor migration cost estimate, making the accumulation visible on an engineering page updated every quarter rather than in a due diligence report produced under deadline by an external team.
- CI/CD pipeline security decision record — the CI/CD security model is the enforcement layer for the dependency intake governance model; a pipeline that verifies published package integrity against cryptographic hashes recorded in the lock file at intake time detects a re-published package with modified contents at build time rather than 34 days into a production deployment; a pipeline that re-resolves dependencies from the package registry on each build trusts whatever the registry serves, which is exactly the trust model that supply chain compromise exploits; the dependency governance ADR specifies which packages are acceptable at intake time and assigns ownership responsibility, while the pipeline security configuration enforces at build time that the packages delivered by the registry match the packages that were evaluated at intake — both layers are required because the governance evaluation at intake is rendered ineffective by the absence of integrity enforcement downstream.
- Dependency update policy decision record — the dependency update policy specifies how quickly security vulnerabilities in existing dependencies are patched and what the SLA timelines are for critical CVE remediation; the dependency inventory provides the named owner who is responsible for executing the patch within those timelines; the two policies are mutually dependent: an update policy without named ownership produces diffuse responsibility for vulnerability remediation, where each engineer who sees the CVE alert assumes that the engineer who added the package is handling it; a named ownership registry without an update policy produces identified responsibility but no timeline commitment, which is not the same as timely remediation; the governance ADR must specify both policies together so that the named owner and the response timeline obligation are always co-located in the same document.
- Open-source extractor — the vendor dependency governance decisions — why the dependency intake criteria were set at 12 months of active maintenance, why the migration complexity threshold that triggers an abstraction layer requirement was set at two engineer-weeks, what alternatives were considered when setting the per-vendor concentration limit and why the 12-engineer-month threshold was chosen over alternatives, why the quarterly review cadence was selected rather than a continuous monitoring approach, what the specific exception conditions were that allowed a known-stale package to remain in the inventory with documented compensating controls — are made in conversations: a CTO and a tech lead debating whether a new infrastructure service requires an abstraction layer before the integration is built; an engineering manager and a security engineer reconstructing the scope of a supply chain compromise by auditing which code paths use the affected package; a VP Engineering and a CTO reviewing the vendor concentration summary after a quarterly inventory review and deciding whether to initiate a migration or accept the current concentration with a documented rationale; the written output is the dependency governance ADR and the dependency inventory; the reasoning behind those decisions — why specific thresholds were chosen, what the tradeoffs between governance strictness and engineering velocity were at each threshold, what the conditions were under which the team would revise the thresholds — lives in the conversation history that preceded the written documentation, and that is exactly what WhyChose's extractor recovers from AI chat export history and makes findable when the engineering team needs to understand not just what the current governance model requires but why the specific requirements were chosen and whether the original conditions that justified them still apply given changes in the product's complexity, the team's size, and the vendor landscape.