What if the supplier changes tomorrow
Vendor risk is how much a feature depends on one supplier you do not control. It matters because a supplier can have an outage, raise a price or withdraw a model, and your feature then stops or costs far more.
You cannot remove the dependency, but you can see it, score it and plan a way out.
By the end of this lesson
Note
I can say how much a feature depends on one supplier and what has no fallback.
Key words
| Word | What it means |
|---|---|
| Dependency | something the feature cannot work without |
| Single point of failure | one dependency with no fallback |
| Withdrawal | a supplier retiring a model you use |
| Switching time | the days it takes to replace a dependency |
| Exit plan | the written steps for leaving a supplier |
The cells students fill in are left blank in this preview.
List what the feature depends on
Write every dependency: the model, the data it reads, the tools it calls. For each, ask three things. Is there a fallback? How long would it take to replace? What happens to users meanwhile?
A dependency with no fallback is a single point of failure. Score it, then work from the top of the list.
Worked example: two dependencies
| Dependency | Weight | No fallback | 60 days to replace | Score |
|---|---|---|---|---|
| Chat model | 3 | doubles to 6 | adds 1 | 7 |
| Docs search | 2 | has a fallback | only 10 days | 2 |
The cells students fill in are left blank in this preview.
Plan a way out before you need it
A supplier can retire a model, change its price or have a long outage. Decide now what you would do: a second model, a cache, a plainer answer, or a pause.
Write the exit plan down and test the second route sometimes. A fallback you never run may not work on the day. The module on cost, tracing and reliability shows how to choose a fallback for each failure.
A common mistake
Warning
Many people think a big supplier cannot fail, so no plan is needed. Big suppliers have outages, change prices and retire models too. Judge each dependency by what happens to your users when it goes, not by the supplier's size.
Write the model helper, part 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// The token counts of a reply, or null when the reply carries none.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the model helper, part 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"status \" + res.status);' ' const data = await res.json();' ' const text = data.choices[0].message.content;' ' return { text, inTokens: count(data, \"prompt_tokens\"), outTokens: count(data, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Recorded sample: no model answered (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the dependency score, part 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' '' '// An invented design: what the feature depends on, whether a fallback exists, and the days to replace it.' 'const design = [' ' { name: \"Chat model\", kind: \"model\", fallback: false, days: 60 },' ' { name: \"Docs search\", kind: \"data\", fallback: true, days: 10 },' ' { name: \"Payments API\", kind: \"tool\", fallback: false, days: 20 },' ' { name: \"Speech to text\", kind: \"model\", fallback: true, days: 45 },' '];' 'const WEIGHT = { model: 3, data: 2, tool: 1 };' > vendor.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the dependency score, part 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'function score(d) {' ' let s = WEIGHT[d.kind];' ' if (d.fallback === false) s = s * 2;' ' if (d.days > 30) s = s + 1;' ' return s;' '}' >> vendor.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the dependency score, part 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' let total = 0;' ' design.forEach(function (d) {' ' total = total + score(d);' ' console.log(d.name + \": \" + score(d) + (d.fallback ? \"\" : \" NO FALLBACK\"));' ' });' ' console.log(\"Total: \" + total);' ' const q = \"List three short questions to ask a supplier before a feature depends on them.\";' ' const r = await ask([{ role: \"user\", content: q }], \"1. How much notice do you give before a price change? 2. How long is an old version kept? 3. How do I export my data?\", 90);' ' console.log(\"One possible list: \" + r.text);' '}' 'main();' >> vendor.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Run the dependency score
docker exec -w /home/node/project agent node vendor.jsShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
One possible output
| Line | What it shows |
|---|---|
| Chat model: 7 NO FALLBACK | The highest score and a single point of failure |
| Docs search: 2 | A fallback and a short switching time |
| Payments API: 2 NO FALLBACK | No fallback, but a low weight |
| Speech to text: 4 | A fallback, but slow to replace |
| Total: 15 | The design as a whole |
| One possible list: ... | Your own call. It differs each run, or says Recorded sample |
The cells students fill in are left blank in this preview.