Skip to content
Back to skills

Caching Strategies 2

ASecurity

Dual-layer caching strategies for the Flare Stack Blog. Use when implementing CDN cache headers, KV caching with versioned invalidation, or debugging cache-related issues.

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 27, 2026
code-qualitytypescriptreactdebuggingapidatabase

Works with

  • api

Security analysis

A100/100

Scanned September 27, 2026

npx -y skills add David-Li0406/meta-skill-evloving --skill caching-strategies-2 --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Caching Strategies 2?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Caching Strategies 2
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/david-li0406-caching-strategies-2/badge)](https://www.skillsdirectory.com/skills/david-li0406-caching-strategies-2)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: caching-strategies
description: Dual-layer caching strategies for the Flare Stack Blog. Use when implementing CDN cache headers, KV caching with versioned invalidation, or debugging cache-related issues.
---

# Caching Strategies

The project employs a dual-layer caching architecture: CDN (HTTP headers) and KV (Cloudflare KV storage).

## CDN Layer (HTTP Headers)

Control browser and CDN caching via response headers set by middlewares.

### Setting Cache Headers

Use `createCacheHeaderMiddleware(strategy)` in Server Functions to set `Cache-Control` headers:

```typescript
import { createServerFn } from "@tanstack/react-start";
import {
  createCacheHeaderMiddleware,
  createRateLimitMiddleware,
} from "@/lib/middlewares";

export const getPostsFn = createServerFn()
  .middleware([
    createRateLimitMiddleware({
      capacity: 60,
      interval: "1m",
      key: "posts:list",
    }),
    createCacheHeaderMiddleware("swr"), // Sets SWR Cache-Control headers
  ])
  .handler(({ context }) => PostService.getPosts(context));
```

### Cache Header Strategies

| Strategy      | Header                 | Use Case             |
| :------------ | :--------------------- | :------------------- |
| `"swr"`       | Stale-While-Revalidate | Public API responses |
| `"immutable"` | Long-term immutable    | Hashed static assets |
| `"private"`   | no-store, private      | Auth/admin responses |

### Cache Control Constants (`lib/constants.ts`)

These constants are used by the middleware factory. Additional constants for error pages:

| Constant                    | Use Case  |
| :-------------------------- | :-------- |
| `CACHE_CONTROL.notFound`    | 404 pages |
| `CACHE_CONTROL.serverError` | 500 pages |

### Invalidation

Purge CDN cache using the Cloudflare API:

```typescript
await purgePostCDNCache(context, post.slug);
```

## KV Layer (Cloudflare KV)

Used for persistent caching of longer-lived data (post lists, details).

### Cache Key Definition

The `CacheKey` type supports both strings and `readonly` arrays (tuples), allowing for type-safe key construction using `as const`.

```typescript
// features/cache/types.ts
export type CacheKey =
  | string
  | readonly (string | number | boolean | null | undefined)[];
```

### Cache Key Factory Pattern

Instead of hardcoding key arrays in services, define **Cache Key Factories** in the feature's `schema.ts`. This provides a single source of truth and ensures types match the requirements of the cache key.

#### 1. Define Factory in `schema.ts`

```typescript
// features/posts/posts.schema.ts
export const POSTS_CACHE_KEYS = {
  /** Post detail cache key (includes version) */
  detail: (version: string, slug: string) => [version, "post", slug] as const,
} as const;
```

#### 2. Use in Service Layer

Pass the tuple directly to `CacheService` functions. No spread (`[...]`) is needed since `CacheKey` supports `readonly` arrays.

```typescript
const version = await CacheService.getVersion(context, "posts:detail");
return await CacheService.get(
  context,
  POSTS_CACHE_KEYS.detail(version, data.slug),
  PostSchema,
  fetcher,
);
```

### Versioned Key Invalidation Strategy

This pattern enables efficient bulk invalidation without iterating through keys:

#### 1. Get Current Version

```typescript
const version = await CacheService.getVersion(context, "posts:detail");
// Returns "v1", "v2", etc.
```

#### 2. Bump Version to Invalidate

When data changes, increment the version number:

```typescript
await CacheService.bumpVersion(context, "posts:detail");
// All old keys with the previous version become unreachable
```

#### 3. Direct Key Deletion

For single-record invalidation, delete the specific key using the factory:

```typescript
const version = await CacheService.getVersion(context, "posts:detail");
await CacheService.deleteKey(context, POSTS_CACHE_KEYS.detail(version, slug));
```

## Complete Example

```typescript
// posts.service.ts
import { POSTS_CACHE_KEYS } from "./posts.schema";

export async function updatePost(
  context: DbContext & { executionCtx: ExecutionContext },
  data: UpdatePostInput,
) {
  // 1. Update in database
  const post = await PostRepo.updatePost(context.db, data);

  // 2. Invalidate KV cache
  await CacheService.bumpVersion(context, "posts:list");
  const version = await CacheService.getVersion(context, "posts:detail");
  await CacheService.deleteKey(context, POSTS_CACHE_KEYS.detail(version, post.slug));

  // 3. Purge CDN cache
  await purgePostCDNCache(context.env, post.slug);

  return post;
}
```

## Cache Namespace Conventions

| Namespace       | Data Type        | Invalidation Trigger          |
| :-------------- | :--------------- | :---------------------------- |
| `posts:list`    | Post listings    | Post create/update/delete     |
| `posts:detail`  | Individual posts | Post update/delete            |
| `tags:list`     | Tag listings     | Tag create/update/delete      |
| `comments:list` | Comment listings | Comment create/approve/delete |

## When to Use Each Layer

| Scenario             | CDN          | KV               |
| :------------------- | :----------- | :--------------- |
| Public API responses | ✅ SWR       | ✅ Version-keyed |
| Admin API responses  | ❌ Private   | Optional         |
| Static assets        | ✅ Immutable | ❌               |
| User-specific data   | ❌ Private   | Depends          |

## Debugging Cache Issues

1. **Stale data after update?**
   - Check if `bumpVersion()` was called
   - Verify CDN purge completed
   - Check cache key construction

2. **Cache misses?**
   - Verify version string consistency
   - Check TTL settings
   - Inspect key serialization

3. **Memory issues?**
   - Review cached data size
   - Consider selective field caching

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…