Offline-First License Validation: How Vend Keeps Your MCP Server Running
License validation that fails when the network hiccups is worse than no validation at all. Here's how Vend's SDK handles caching, timeouts, and offline fallback.
The reliability problem
MCP servers run locally on the user's machine. They start when the AI client launches and stay running for hours. During that time, network conditions change: Wi-Fi drops, VPNs reconnect, laptops go to sleep on trains.
If your license validation requires a network call every time a user invokes a tool, a 2-second network blip means the AI assistant tells your paying customer: “Sorry, I can't use that tool right now.” That's a terrible experience.
Vend's SDK is designed around a simple principle: a validated user should never be blocked by a transient network failure.
The caching layer
When the SDK validates a license key against the Vend API, it caches the result locally. Subsequent calls to guard.canAccess() hit the cache instead of the network:
- Successful validations are cached for 5 minutes by default. During this window, tool access checks are instant — no network call, no latency.
- Failed validations are cached for 30 seconds. This prevents hammering the API with a bad key, but allows legitimate users to retry quickly after fixing their key.
Both TTLs are configurable:
const guard = vendAuth({
apiKey: process.env.VEND_API_KEY!,
cacheTtl: 600, // 10 minutes for valid keys
errorCacheTtl: 10, // 10 seconds for invalid keys
gates: { /* ... */ },
});Offline fallback
Here's where it gets interesting. When the cache expires and the SDK tries to re-validate, what happens if the network is down?
The SDK keeps the last successful validation in memory with a separate, longer TTL: 1 hour. If a re-validation call fails due to a network error, the SDK falls back to this stale-but-valid cache entry.
In practice, this means:
- Minutes 0–5: Cached, instant. No network call.
- Minute 5: Cache expires. SDK re-validates over the network. If successful, cache resets.
- Minute 5, network down: SDK uses the stale cache. User is not blocked.
- Minute 65, still offline: Stale cache expires. Validation fails. User is blocked.
The 1-hour window is a deliberate tradeoff. It's long enough to survive any realistic network interruption (Wi-Fi switch, VPN reconnect, brief outage), but short enough that a revoked key doesn't stay valid forever.
Lazy validation
The SDK doesn't validate the license key when you call vendAuth(). It waits until the first call to guard.canAccess() or guard.validate(). This is intentional:
- Your MCP server starts up instantly, even if the network is slow.
- No wasted API calls if the user never invokes a gated tool.
- The validation happens in the context of the first tool call, where you can handle failures gracefully.
What happens at the edges
Let's walk through the failure scenarios:
User has never validated (cold start, no network)
The SDK has no cached result. It tries to validate over the network. The network is down. Validation fails. This is the one case where the user is blocked — and it's the correct behavior, because we've never confirmed this key is valid.
User validated recently, network drops
The cached result is used. The user continues working. When the network returns, the next cache expiry triggers a successful re-validation.
Key is revoked while user is offline
The stale cache continues to grant access for up to 1 hour. After that, the SDK must re-validate, discovers the key is revoked, and blocks access. This is the tradeoff: you accept up to 1 hour of “stale access” in exchange for never blocking legitimate users during network issues.
Vend API is down
Same behavior as a network failure. The stale cache kicks in. Previously validated users are not affected. This means a Vend outage doesn't cascade into your MCP server being unusable.
Performance: sub-50ms validation
When the cache is warm (which is most of the time), validation is a local memory lookup. There's no network call, no database query, no serialization. It's effectively instant.
When a network call is needed, Vend's validation API is optimized for speed — a single indexed database query, no joins, targeting under 50ms end-to-end. The SDK never blocks your tool response waiting for a slow network.
Fire-and-forget usage recording
Usage recording follows the same philosophy. When you call guard.recordUsage(), the API call happens in the background. Your tool response is returned immediately. If the usage recording fails (network issue, API error), it fails silently — the user's tool call is never affected.
This means a network problem never causes a double penalty: the user isn't blocked from using the tool and isn't blocked from getting a response. Reliability is additive, not subtractive.
Design principles
The SDK's caching strategy is built on three principles:
- Validated users should never be blocked by transient failures. Once we know a key is valid, we trust that knowledge for a reasonable window.
- Invalid keys should fail fast. Bad keys are cached briefly to prevent API abuse, but re-checked quickly so legitimate users aren't stuck.
- The MCP server is always the priority. Vend is infrastructure. If Vend is slow or down, your MCP server should still work for validated users.
Build on infrastructure that respects your users' experience. Get started with Vend and ship an MCP server that works even when the network doesn't.