A free VIN decode that always hits live NHTSA DecodeVinValues on every paste pays cold-start latency for makes you already decode often. ETag revalidation and quota headers are covered elsewhere. This post is different: warm a small cache of successful decode bodies for popular make patterns before peak traffic, label every hit as cached, and never invent missing catalog rows to make a warmed card look complete.
The goal is honest pre-fetch: store only bodies you actually received from vPIC, bound the warm set so you do not hammer upstream, and refuse folklore fills when a warmed entry lacks a field.
Warm cache vs other cache tools
Use make-pattern warmup when:
- You already see a stable set of popular Makes (or Make+ModelYear buckets) in traffic
- You can schedule a bounded pre-fetch of real DecodeVinValues responses you are allowed to store
- Interactive UI can disclose "cached decode" vs "live decode"
Do not use warmup to:
- Fabricate Make/Model/Year/spec rows for VINs you never decoded
- Bypass ETag / If-None-Match when you already have a fresh body for that VIN
- Ignore upstream rate-limit headers while filling the warm set
- Pretend a warmed partial body is a complete safety or options package
If the warm set has no entry for a VIN, call live decode or show loading -- do not invent rows so the card looks full.
Bound the warm set
Key by normalized VIN. Store only successful vPIC bodies. Cap how many VINs you warm per make and how often the job runs.
export type WarmEntry = {
vinNormalized: string;
make: string;
body: Record<string, string | null>;
fetchedAt: number; // epoch ms of live DecodeVinValues success
source: "vpic";
};
export type WarmStore = Map<string, WarmEntry>;
export type WarmPlan = {
make: string;
vins: string[]; // already normalized, capped
maxPerMake: number;
};
export function planWarmup(
popularMakes: { make: string; sampleVins: string[] }[],
maxPerMake = 25,
): WarmPlan[] {
return popularMakes.map(({ make, sampleVins }) => ({
make,
maxPerMake,
vins: sampleVins.slice(0, maxPerMake),
}));
}
export async function runWarmup(
store: WarmStore,
plans: WarmPlan[],
decodeLive: (vin: string) => Promise<Record<string, string | null>>,
sleepMs: (ms: number) => Promise<void>,
gapMs = 250,
): Promise<{ warmed: number; skipped: number }> {
let warmed = 0;
let skipped = 0;
for (const plan of plans) {
for (const vin of plan.vins) {
if (store.has(vin)) {
skipped += 1;
continue;
}
const body = await decodeLive(vin);
store.set(vin, {
vinNormalized: vin,
make: plan.make,
body: { ...body },
fetchedAt: Date.now(),
source: "vpic",
});
warmed += 1;
await sleepMs(gapMs);
}
}
return { warmed, skipped };
}
Space calls with gapMs and respect any upstream quota path you already run. Warmup is not a license to burst past NHTSA limits.
Serve warmed hits with disclosure
A warm hit is still a prior live decode -- not a guarantee that every catalog field is present, and not permission to fill blanks.
const EMPTY = new Set([
"",
"not applicable",
"n/a",
"na",
"null",
"none",
"unknown",
]);
export type DecodeServe = {
body: Record<string, string | null>;
source: "warm-cache" | "live";
fetchedAt: number;
};
export function serveDecode(
store: WarmStore,
vinNormalized: string,
live: DecodeServe | null,
): DecodeServe | null {
if (live) return live;
const hit = store.get(vinNormalized);
if (!hit) return null;
return {
body: { ...hit.body },
source: "warm-cache",
fetchedAt: hit.fetchedAt,
};
}
export function fieldOrMissing(
body: Record<string, string | null>,
key: string,
): string {
const raw = (body[key] ?? "").trim();
if (!raw || EMPTY.has(raw.toLowerCase())) {
return "not provided";
}
return raw;
}
export function assertNoWarmInvent(moduleSource: string): void {
const banned = [
/spec.?complete/i,
/full.?options.?package/i,
/invent(?:ed|ing)?\s+catalog/i,
/folklore.?fill/i,
/assumed.?standard/i,
];
for (const re of banned) {
if (re.test(moduleSource)) {
throw new Error(
`Warm-cache module must not invent spec completeness: ${re}`,
);
}
}
}
UI copy should say the decode came from warm cache when source === "warm-cache", including fetchedAt. Missing keys stay "not provided" -- never "assumed Standard for this make."
Forbidden upgrades
Product pressure often asks for:
- Filling blank catalog fields from Make averages so warmed cards look "complete"
- Warming fabricated VINs or synthetic bodies you never received from vPIC
- Skipping rate gaps and quota handling during the warm job
- Labeling a warm hit as a fresh live decode
- Treating a warm hit as proof that every safety option is present
Refuse those. Completeness is whatever vPIC returned on that VIN -- not what marketing expects for the make.
Quick checks
import assert from "node:assert/strict";
const store: WarmStore = new Map();
const plans = planWarmup(
[{ make: "TOYOTA", sampleVins: ["VIN1", "VIN2", "VIN3"] }],
2,
);
assert.equal(plans[0].vins.length, 2);
const fakeLive = async (vin: string) => ({
Make: "TOYOTA",
Model: vin === "VIN1" ? "Camry" : "",
ABS: "",
});
await runWarmup(store, plans, fakeLive, async () => {}, 0);
assert.equal(store.size, 2);
const served = serveDecode(store, "VIN1", null);
assert.equal(served?.source, "warm-cache");
assert.equal(fieldOrMissing(served!.body, "Make"), "TOYOTA");
assert.equal(fieldOrMissing(served!.body, "ABS"), "not provided");
assert.ok(!/assumed|complete|standard for make/i.test(
fieldOrMissing(served!.body, "ABS"),
));
assert.equal(serveDecode(store, "UNKNOWN", null), null);
Review rule: warm-cache modules must not invent catalog completeness phrases except in forbidding tests. Never upgrade a blank field because the make is popular.
UI copy that stays honest
Prefer "Showing cached decode from warm set (fetched …)" and keep blank fields as "not provided" even for popular Makes. Avoid "Full specs for this make -- preloaded," "Assumed Standard for Toyota," or relabeling a warm hit as a live DecodeVinValues response.
Takeaway
Warming a VIN decode cache for popular makes is a latency tool, not a completeness tool. Store only real vPIC bodies, bound the job, disclose cache hits, and leave empty fields as "not provided." Your free VIN UI stays trustworthy when a warm hit is a dated prior decode -- never a folklore-filled "full spec" card.
I maintain VIN Lookup, a free VIN decode based on NHTSA data.
Top comments (0)