-
Notifications
You must be signed in to change notification settings - Fork 0
Admin Hooks
Admin hooks are required to manage a Durable Object's storage through DO Manager. This guide covers setup options.
Admin hooks expose HTTP endpoints on your Durable Object that DO Manager uses to:
- List and read storage keys/values
- Create, update, and delete keys
- Execute SQL queries (SQLite-backed DOs)
- Manage alarms
- Export and import data
The easiest way to add admin hooks is with the official NPM package.
npm install do-manager-admin-hooksimport { withAdminHooks } from "do-manager-admin-hooks";
export class MyDurableObject extends withAdminHooks() {
async fetch(request: Request): Promise<Response> {
// Handle admin requests first (required for DO Manager)
const adminResponse = await this.handleAdminRequest(request);
if (adminResponse) return adminResponse;
// Your custom logic here
return new Response("Hello from my Durable Object!");
}
}That's it! The package handles all admin endpoints automatically.
export class SecureDO extends withAdminHooks({
basePath: "/admin", // Change admin endpoint path (default: '/admin')
requireAuth: true, // Require authentication
adminKey: "secret-key", // Admin key for auth
}) {
async fetch(request: Request): Promise<Response> {
const adminResponse = await this.handleAdminRequest(request);
if (adminResponse) return adminResponse;
return new Response("Hello!");
}
}If you prefer not to use the NPM package, you can copy-paste the admin hook code directly.
- In DO Manager, navigate to a namespace
- Click Get Admin Hook Code
- Copy the generated TypeScript code
- Paste into your Durable Object class
export class MyDurableObject implements DurableObject {
state: DurableObjectState;
constructor(state: DurableObjectState) {
this.state = state;
}
async fetch(request: Request): Promise<Response> {
const url = new URL(request.url);
// Admin hook endpoints
if (url.pathname.startsWith("/admin")) {
return this.handleAdmin(request, url);
}
// Your business logic
return new Response("OK");
}
async handleAdmin(request: Request, url: URL): Promise<Response> {
const path = url.pathname.replace("/admin", "");
switch (path) {
case "/list":
return this.adminList();
case "/get":
return this.adminGet(url.searchParams.get("key"));
case "/put":
return this.adminPut(request);
case "/delete":
return this.adminDelete(request);
case "/export":
return this.adminExport();
case "/import":
return this.adminImport(request);
case "/alarm":
return this.adminAlarm(request);
default:
return new Response("Not Found", { status: 404 });
}
}
// Implement each admin method...
}After adding admin hooks to your Durable Object:
- Deploy your Worker with admin hooks installed
- In DO Manager, add or edit the namespace
- Set the Admin Hook Endpoint URL (e.g.,
https://my-worker.workers.dev) - Save the namespace
- The green Admin Hook Enabled badge confirms it's working
Tip: You can set the endpoint URL when creating a namespace, or add it later via Settings.
All endpoints are prefixed with the base path (default: /admin).
| Endpoint | Method | Description |
|---|---|---|
/admin/list |
GET | List all storage keys (KV) or tables (SQLite) |
/admin/get?key=X |
GET | Get value for a specific key |
/admin/put |
POST | Set a key-value pair |
/admin/delete |
POST | Delete a key |
| Endpoint | Method | Description |
|---|---|---|
/admin/sql |
POST | Execute SQL query |
| Endpoint | Method | Description |
|---|---|---|
/admin/alarm |
GET | Get current alarm state |
/admin/alarm |
PUT | Set new alarm |
/admin/alarm |
DELETE | Delete existing alarm |
| Endpoint | Method | Description |
|---|---|---|
/admin/export |
GET | Export all storage as JSON |
/admin/import |
POST | Import data from JSON |
Used for migration cutover mode "Copy + Freeze Source".
| Endpoint | Method | Description |
|---|---|---|
/admin/:name/freeze |
PUT | Freeze instance (block writes) |
/admin/:name/freeze |
DELETE | Unfreeze instance (allow writes) |
/admin/:name/freeze |
GET | Get current freeze status |
When frozen, PUT, DELETE, and IMPORT operations return 423 Locked.
Request:
GET /admin/list
Response:
{
"keys": ["key1", "key2", "key3"]
}Request:
GET /admin/list
Response:
{
"tables": ["users", "sessions", "logs"]
}Request:
GET /admin/get?key=mykey
Response:
{
"key": "mykey",
"value": { "data": "example" }
}Request:
POST /admin/put
Content-Type: application/json
{
"key": "mykey",
"value": { "data": "example" }
}
Response:
{
"success": true
}Request:
POST /admin/delete
Content-Type: application/json
{
"key": "mykey"
}
Response:
{
"success": true
}Request:
POST /admin/sql
Content-Type: application/json
{
"query": "SELECT * FROM users LIMIT 10"
}
Response:
{
"columns": ["id", "name", "email"],
"rows": [
[1, "Alice", "alice@example.com"],
[2, "Bob", "bob@example.com"]
]
}Request:
GET /admin/export
Response:
{
"data": {
"key1": "value1",
"key2": { "nested": "data" }
},
"exportedAt": "2025-11-29T00:00:00Z",
"keyCount": 2
}Request:
POST /admin/import
Content-Type: application/json
{
"data": {
"key1": "value1",
"key2": { "nested": "data" }
}
}
Response:
{
"success": true,
"imported": 2
}- Ensure admin hook methods are added to your DO class
- Set the endpoint URL in namespace settings
- Verify your Worker is deployed
- Ensure export returns:
{ data: {...}, exportedAt: "...", keyCount: N } - Ensure import accepts:
{ data: {...} } - The NPM package handles this automatically
- Check the Worker logs in Cloudflare dashboard
- Verify the endpoint URL is correct
- Ensure CORS headers are set if accessing cross-origin