Skip to content

Admin Hooks

Temp edited this page Jan 27, 2026 · 3 revisions

Admin Hooks

Admin hooks are required to manage a Durable Object's storage through DO Manager. This guide covers setup options.


Overview

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

Option A: NPM Package (Recommended)

The easiest way to add admin hooks is with the official NPM package.

Installation

npm install do-manager-admin-hooks

Basic Usage

import { 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.

Configuration Options

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!");
  }
}

Links


Option B: Manual Setup

If you prefer not to use the NPM package, you can copy-paste the admin hook code directly.

Get the Code

  1. In DO Manager, navigate to a namespace
  2. Click Get Admin Hook Code
  3. Copy the generated TypeScript code
  4. Paste into your Durable Object class

Manual Implementation Example

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...
}

Enable Admin Hooks in DO Manager

After adding admin hooks to your Durable Object:

  1. Deploy your Worker with admin hooks installed
  2. In DO Manager, add or edit the namespace
  3. Set the Admin Hook Endpoint URL (e.g., https://my-worker.workers.dev)
  4. Save the namespace
  5. 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.


Admin Endpoints Reference

All endpoints are prefixed with the base path (default: /admin).

Storage Operations

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

SQL Operations (SQLite only)

Endpoint Method Description
/admin/sql POST Execute SQL query

Alarm Operations

Endpoint Method Description
/admin/alarm GET Get current alarm state
/admin/alarm PUT Set new alarm
/admin/alarm DELETE Delete existing alarm

Bulk Operations

Endpoint Method Description
/admin/export GET Export all storage as JSON
/admin/import POST Import data from JSON

Freeze Operations

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/Response Formats

List Keys (KV)

Request:

GET /admin/list

Response:

{
  "keys": ["key1", "key2", "key3"]
}

List Tables (SQLite)

Request:

GET /admin/list

Response:

{
  "tables": ["users", "sessions", "logs"]
}

Get Value

Request:

GET /admin/get?key=mykey

Response:

{
  "key": "mykey",
  "value": { "data": "example" }
}

Put Value

Request:

POST /admin/put
Content-Type: application/json

{
  "key": "mykey",
  "value": { "data": "example" }
}

Response:

{
  "success": true
}

Delete Key

Request:

POST /admin/delete
Content-Type: application/json

{
  "key": "mykey"
}

Response:

{
  "success": true
}

Execute SQL

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"]
  ]
}

Export Storage

Request:

GET /admin/export

Response:

{
  "data": {
    "key1": "value1",
    "key2": { "nested": "data" }
  },
  "exportedAt": "2025-11-29T00:00:00Z",
  "keyCount": 2
}

Import Storage

Request:

POST /admin/import
Content-Type: application/json

{
  "data": {
    "key1": "value1",
    "key2": { "nested": "data" }
  }
}

Response:

{
  "success": true,
  "imported": 2
}

Troubleshooting

"Admin hook not configured"

  • Ensure admin hook methods are added to your DO class
  • Set the endpoint URL in namespace settings
  • Verify your Worker is deployed

Clone creates empty instance

  • Ensure export returns: { data: {...}, exportedAt: "...", keyCount: N }
  • Ensure import accepts: { data: {...} }
  • The NPM package handles this automatically

Admin requests failing

  • Check the Worker logs in Cloudflare dashboard
  • Verify the endpoint URL is correct
  • Ensure CORS headers are set if accessing cross-origin

Clone this wiki locally