Caching

Memory and Redis cache options with automatic invalidation.

The SDK caches entitlement lookups to avoid hitting your payment provider on every request.

Memory cache (default)

import { createEnhancedClient } from "@fuime/billing-sdk";
import { stripe } from "@fuime/billing-sdk/stripe";

const billing = createEnhancedClient({
  provider: stripe({ apiKey: process.env.STRIPE_KEY }),
  cache: {
    ttlMs: 60_000, // 1 minute
  },
});

Memory cache is perfect for:

  • Single-server deployments
  • Development and testing
  • Low-traffic applications

Redis cache

For multi-server deployments, use Redis:

import { createEnhancedClient } from "@fuime/billing-sdk";
import { stripe } from "@fuime/billing-sdk/stripe";
import { redisCache } from "@fuime/billing-sdk/cache/redis";
import { Redis } from "ioredis";

const redis = new Redis(process.env.REDIS_URL);

const billing = createEnhancedClient({
  provider: stripe({ apiKey: process.env.STRIPE_KEY }),
  cache: redisCache({
    client: redis,
    ttlMs: 60_000,
    prefix: "billing:", // Optional key prefix
  }),
});

How caching works

Request: hasFeature("user_123", "api")
         │
         ▼
    ┌─────────┐
    │  Cache  │ ──── Hit? ──── Return cached entitlement
    └────┬────┘
         │ Miss
         ▼
    ┌──────────┐
    │ Provider │ ──── Fetch from Stripe/Polar
    └────┬─────┘
         │
         ▼
    Store in cache with TTL
         │
         ▼
    Return entitlement

Automatic invalidation

When a webhook arrives, the SDK automatically invalidates the cache for that user:

// In your webhook handler
const event = await billing.parseWebhook(body, signature);
// Cache for event.userId is automatically cleared

This means:

  • User upgrades → immediate access to new features
  • User cancels → immediate loss of access
  • No stale data between webhook and next request

Manual invalidation

// Invalidate a single user
billing.invalidateCache("user_123");

// Invalidate all users (use sparingly)
billing.clearCache();

Cache configuration

OptionTypeDefaultDescription
ttlMsnumber60000Time-to-live in milliseconds
prefixstring"billing:"Key prefix (Redis only)

Disabling cache

For testing or debugging:

const billing = createEnhancedClient({
  provider: stripe({ apiKey: process.env.STRIPE_KEY }),
  cache: { ttlMs: 0 }, // Disable caching
});

Warning: Disabling cache means every hasFeature or getEntitlement call hits your provider's API.