This site is not affiliated with or endorsed by Cloudflare, Inc. It showcases deployable experiments across most Cloudflare products.
Storage & Data

KV Notes

Simple note CRUD with Workers KV at the edge - minimal key-value storage reference for Cloudflare Workers

Store and retrieve small text notes using a dedicated Workers KV namespace.

API Reference

POST /notes

Create or update a note.

Prop

Type

Example Request

curl -X POST "https://your-worker.workers.dev/notes" \
  -H "Content-Type: application/json" \
  -d '{"id":"todo-1","content":"Ship the experiment"}'

Success Response

{
  "id": "todo-1",
  "content": "Ship the experiment",
  "updatedAt": "2025-06-20T12:00:00.000Z"
}

GET /notes

Fetch a note by id.

id string (required)

Example Request

curl "https://your-worker.workers.dev/notes?id=todo-1"

DELETE /notes

Delete a note by id.

id string (required)

Error Codes

  • 400 - Invalid id or content (INVALID_ID, INVALID_CONTENT, INVALID_BODY)
  • 404 - Note not found (NOT_FOUND)

Use Cases

  • Learn KV read/write/delete patterns without D1
  • Store small configuration blobs at the edge
  • Prototype simple key-value APIs before adding auth

Limitations

  • Note IDs are capped at 64 characters; content at 4,000 characters
  • No authentication; any client can read, write, or delete by ID
  • KV is eventually consistent across edge locations

Use in your project

Copy these files into an existing Worker. Prefer Deployment to try the full experiment first. Source: apps/experiments/kv-notes.

DependenciesNoneBindingsKVPlatformWorkers runtime
import {  MAX_CONTENT_LENGTH,  MAX_NOTE_ID_LENGTH,  NOTE_ID_PATTERN,  NOTE_KEY_PREFIX,} from "../constants/defaults";export function validateNoteId(input: string | undefined): string | null {  if (!input || typeof input !== "string") return null;  const trimmed = input.trim();  if (!trimmed || trimmed.length > MAX_NOTE_ID_LENGTH) return null;  if (!NOTE_ID_PATTERN.test(trimmed)) return null;  return trimmed;}export function validateContent(input: string | undefined): string | null {  if (!input || typeof input !== "string") return null;  const trimmed = input.trim();  if (!trimmed || trimmed.length > MAX_CONTENT_LENGTH) return null;  return trimmed;}export function noteKey(id: string): string {  return `${NOTE_KEY_PREFIX}${id}`;}export async function getNote(kv: KVNamespace, id: string): Promise<string | null> {  return kv.get(noteKey(id));}export async function saveNote(kv: KVNamespace, id: string, content: string): Promise<void> {  const record = {    id,    content,    updatedAt: new Date().toISOString(),  };  await kv.put(noteKey(id), JSON.stringify(record));}export async function deleteNote(kv: KVNamespace, id: string): Promise<void> {  await kv.delete(noteKey(id));}export function parseNoteRecord(  raw: string,  id: string): { id: string; content: string; updatedAt: string } | null {  try {    const parsed = JSON.parse(raw) as { id?: string; content?: string; updatedAt?: string };    if (!parsed.content || typeof parsed.content !== "string") return null;    return {      id: parsed.id ?? id,      content: parsed.content,      updatedAt: parsed.updatedAt ?? new Date(0).toISOString(),    };  } catch {    return null;  }}

Deployment

Click the deploy button

Deploy to Cloudflare Workers

Configure KV

Create a KV namespace and bind it as NOTES in wrangler.json.

Local Development

cd apps/experiments/kv-notes
npm install
npm run dev

Cloudflare Features Used

On this page