Last Updated: November 5, 2025
A modern, full-featured web application for managing Cloudflare Workers KV namespaces and keys, with enterprise-grade authentication via Cloudflare Access Zero Trust.
🎯 Try the Live Demo - See KV Manager in action
📰 Read the v1.0.0 Release Article - Learn more about features, architecture, and deployment
- Create, delete, and rename KV namespaces
- Browse namespaces with key counts and metadata
- Export entire namespaces to JSON or NDJSON format
- Import keys from JSON or NDJSON files
- Namespace-level audit logging
- List keys with cursor-based pagination
- Create, update, and delete individual keys
- Full CRUD operations with metadata support
- TTL (expiration) management
- KV native metadata (1024 byte limit)
- Single-version backup and restore
- Add unlimited tags to keys for organization
- Store custom JSON metadata (no size limit)
- Search and filter by tags
- Bulk tag operations (add/remove/replace)
- Separate from KV's native metadata system
- Cross-namespace search by key name
- Filter by specific namespaces
- Filter by tags (multiple tag support)
- Real-time search with debouncing
- Quick navigation to search results
- Bulk Delete: Remove multiple keys at once
- Bulk Copy: Copy keys between namespaces
- Bulk TTL Update: Set expiration on multiple keys
- Bulk Tag: Apply tags to multiple keys
- Progress tracking with job IDs
- Batch processing (10,000 keys per operation)
- Export namespaces in JSON or NDJSON format
- Auto-detect format on import
- Collision handling (skip/overwrite/fail)
- Progress tracking for large operations
- Download exported data as files
- Track all operations with user attribution
- Filter by namespace or user
- Filter by operation type
- Pagination support
- Export audit logs to CSV
- Comprehensive operation tracking
- Dark/Light Theme: System, light, and dark theme support
- Navigation: Switch between Namespaces, Search, and Audit Log views
- Responsive Design: Works on desktop and mobile
- Modern UI: Built with shadcn/ui components and Tailwind CSS
- Frontend: React 19.2.0 + TypeScript 5.9.3 + Vite 7.1.12 + Tailwind CSS 3.4.18 + shadcn/ui
- Backend: Cloudflare Workers + KV + D1 (metadata) + Durable Objects (orchestration)
- Auth: Cloudflare Access (Zero Trust)
🐳 Quick Start with Docker
Pull the latest image:
docker pull writenotenow/kv-manager:latestRun the container:
docker run -d \
-p 8787:8787 \
-e ACCOUNT_ID=your_cloudflare_account_id \
-e API_KEY=your_cloudflare_api_token \
-e TEAM_DOMAIN=https://yourteam.cloudflareaccess.com \
-e POLICY_AUD=your_cloudflare_access_aud_tag \
--name kv-manager \
writenotenow/kv-manager:latestAccess at http://localhost:8787
📖 Full Docker Documentation: See DOCKER_README.md for complete deployment guides including:
- Docker Compose configurations
- Kubernetes deployments
- Reverse proxy examples (Nginx, Traefik, Caddy)
- Security best practices
- Troubleshooting guide
- Node.js 18+
- npm or yarn
- Wrangler CLI (
npm install -g wrangler)
- Install dependencies:
npm install- Create environment file:
cp .env.example .env- Initialize local D1 database:
npx wrangler d1 execute kv-manager-metadata-dev --local --file=worker/schema.sql- Start the development servers:
In Terminal 1, start the frontend:
npm run devIn Terminal 2, start the worker:
npx wrangler dev --config wrangler.dev.toml --local- Access the application:
- Frontend: http://localhost:5173
- Worker API: http://localhost:8787
- Authentication is bypassed for localhost requests
- Mock data is returned when no Cloudflare credentials are provided
- No secrets required for local development
- CORS is configured to allow
http://localhost:5173
- Cloudflare account
- Domain (optional, can use workers.dev)
- Cloudflare Access configured for your domain
- Create production configuration:
cp wrangler.toml.example wrangler.toml- Create D1 database:
wrangler d1 create kv-manager-metadataCopy the database_id from the output to your wrangler.toml file.
- Initialize D1 schema:
wrangler d1 execute kv-manager-metadata --remote --file=worker/schema.sql- Set secrets:
Set your Cloudflare Account ID:
wrangler secret put ACCOUNT_IDSet your API Key:
wrangler secret put API_KEYSet your Team Domain:
wrangler secret put TEAM_DOMAINSet your Policy AUD tag:
wrangler secret put POLICY_AUD- Build and deploy:
Build the application:
npm run buildDeploy to Cloudflare:
wrangler deploy- All API requests require valid Cloudflare Access JWT
- Audit logging captures all destructive operations
- D1 stores metadata, tags, and audit logs
- Durable Objects handle bulk operations exceeding 10,000 keys
GET /api/namespaces- List all namespacesPOST /api/namespaces- Create a new namespaceDELETE /api/namespaces/:id- Delete a namespacePATCH /api/namespaces/:id/rename- Rename a namespaceGET /api/namespaces/:id/info- Get namespace information and statistics
GET /api/keys/:namespaceId/list- List keys with cursor-based paginationGET /api/keys/:namespaceId/:keyName- Get a key's value and metadataPUT /api/keys/:namespaceId/:keyName- Create or update a keyDELETE /api/keys/:namespaceId/:keyName- Delete a keyPOST /api/keys/:namespaceId/bulk-delete- Delete multiple keysPOST /api/keys/:namespaceId/bulk-copy- Copy keys to another namespacePOST /api/keys/:namespaceId/bulk-ttl- Update TTL on multiple keys
GET /api/metadata/:namespaceId/:keyName- Get D1-backed metadata and tagsPUT /api/metadata/:namespaceId/:keyName- Update metadata and tagsPOST /api/metadata/:namespaceId/bulk-tag- Apply tags to multiple keys (add/remove/replace)
GET /api/search- Search keys across namespaces- Query params:
query(key name pattern),namespace_id,tags(comma-separated)
- Query params:
POST /api/backup/:namespaceId/:keyName/undo- Restore key to previous versionGET /api/backup/:namespaceId/:keyName/check- Check if backup exists
GET /api/export/:namespaceId- Export namespace keys and values- Query params:
format(json|ndjson)
- Query params:
POST /api/import/:namespaceId- Import keys into namespace- Query params:
collision(skip|overwrite|fail)
- Query params:
GET /api/jobs/:jobId- Get status of import/export job
GET /api/audit/:namespaceId- Get audit log for a namespace- Query params:
limit,offset,operation
- Query params:
GET /api/audit/user/:userEmail- Get audit log for a specific user- Query params:
limit,offset,operation
- Query params:
The D1 database (kv-manager-metadata) stores:
- Stores tags and custom metadata for keys
- JSON fields for flexible schema
- Indexed by
namespace_idandkey_name
- Tracks all operations (create, update, delete, bulk operations)
- User attribution via email
- Timestamp, operation type, and details
- Indexed for efficient querying
- Tracks import/export and bulk operation progress
- Status tracking (queued, running, completed, failed)
- Progress counters (total, processed, errors)
- Job metadata and timestamps
- First and last accessed timestamps
- Namespace-level statistics
See worker/schema.sql for the complete schema definition.
- Namespaces View: Browse and manage KV namespaces
- Search View: Cross-namespace key search with filters
- Audit Log View: Operation history and tracking
- System (default): Follows OS preference
- Light: Light mode
- Dark: Dark mode
Theme preference is stored in localStorage and persists across sessions.
- Cloudflare Access JWT validation on all API requests
- Auth bypassed for localhost development
- All KV operations require valid auth token
- Audit logging of all destructive operations
- Protected namespaces hidden from UI
- View all namespaces on the main page
- Click Create Namespace to add a new one
- Use Export to download namespace data (JSON/NDJSON)
- Use Import to upload keys from a file
- Click Browse Keys to view namespace contents
- Use the three-dot menu for rename/delete operations
- Browse keys in a namespace with pagination
- Click Add Key to create a new key-value pair
- Select multiple keys using checkboxes for bulk operations
- Edit individual keys by clicking on them
- View and modify TTL (expiration) settings
- Add tags and custom metadata in the "Metadata & Tags" tab
- Select multiple keys using checkboxes
- Choose from available bulk actions:
- Copy to Namespace: Duplicate keys to another namespace
- Update TTL: Set expiration time on selected keys
- Apply Tags: Add, remove, or replace tags
- Delete Selected: Remove multiple keys at once
- Monitor progress with job status tracking
- Click Search in the navigation bar
- Enter a key name pattern (supports partial matches)
- Filter by specific namespace (optional)
- Filter by tags (comma-separated, optional)
- Click any result to navigate to that key
- Click Audit Log in the navigation bar
- Select a namespace to view its operation history
- Filter by operation type (create, update, delete, etc.)
- Use pagination to browse historical entries
- Export logs to CSV for external analysis
Ensure wrangler is installed:
npm install -g wranglerCheck Node.js version (18+ required):
node --versionTry clearing Wrangler cache:
rm -rf ~/.wrangler- Verify
VITE_WORKER_APIin.envpoints tohttp://localhost:8787 - Check CORS configuration in
worker/utils/cors.ts - Ensure both dev servers are running
Reinitialize the schema:
npx wrangler d1 execute kv-manager-metadata-dev --local --file=worker/schema.sqlCheck D1 binding in wrangler.dev.toml
Verify database exists:
npx wrangler d1 list- Mock data is only returned when
ACCOUNT_IDandAPI_KEYare not set - Check console logs for
[Auth] Localhost detected, skipping JWT validation - Ensure worker is running with
--localflag
- Verify file format is valid JSON or NDJSON
- Check file size (large imports may take time)
- Monitor job status using the returned
job_id - Check browser console for detailed error messages
- Ensure metadata exists in D1 database
- Check that keys have been tagged (if filtering by tags)
- Verify D1 database is properly initialized
- Try searching without filters first
- Add WebSocket support for real-time progress
- Implement Durable Objects for large operations
- Add advanced search filters
- Create analytics dashboard
- R2 backup integration
- Scheduled jobs (cron triggers)
- Full version history
- Key expiration alerts
- Namespace templates
- Batch operations to R2
MIT
Contributions welcome! Please open an issue or PR.