04 — Database (D1)

Your D1 SQLite database is ready to use. Learn how to connect, query, migrate, and back up.

Connection String

Your database is scoped to your account. Connection details:

Database ID: drklynx-m-db-abc123def456
Account ID: (in your credentials email)
API Token: (in your credentials email)

You don't need a traditional connection string. Instead, you use Wrangler CLI or make API calls with your token.

Querying via Wrangler CLI

The quickest way to test queries.

Create a Table

wrangler d1 execute drklynx-m-db-abc123def456 --remote \
  --command "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT);"

You'll see:

✓ Executed successfully

Insert Data

wrangler d1 execute drklynx-m-db-abc123def456 --remote \
  --command "INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');"

Query Data

wrangler d1 execute drklynx-m-db-abc123def456 --remote \
  --command "SELECT * FROM users;"

Output:

┌────┬───────┬──────────────────────┐
│ id │ name  │ email                │
├────┼───────┼──────────────────────┤
│ 1  │ Alice │ alice@example.com    │
└────┴───────┴──────────────────────┘

Querying from Your Pages Functions

Your Pages project can query D1 directly from JavaScript/TypeScript functions.

Example: Pages Function

Create functions/api/users.js:

export async function onRequest({ env }) {
  const db = env.DB;
  const result = await db.prepare('SELECT * FROM users').all();
  return new Response(JSON.stringify(result), {
    headers: { 'Content-Type': 'application/json' },
  });
}

Then in your wrangler.toml:

[[d1_databases]]
binding = "DB"
database_name = "drklynx-m-db-abc123def456"
database_id = "abc123def456"

Deploy with:

wrangler pages deploy ./build

Now GET /api/users returns your users as JSON.

Schema Migrations

As your app grows, you'll need to modify your database schema. Use SQL migration files to keep track of changes.

Create a Migrations Folder

mkdir -p migrations

Write a Migration

migrations/001_init.sql:

CREATE TABLE users (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  email TEXT UNIQUE NOT NULL,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE posts (
  id INTEGER PRIMARY KEY,
  user_id INTEGER NOT NULL,
  title TEXT NOT NULL,
  content TEXT,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  FOREIGN KEY (user_id) REFERENCES users(id)
);

Apply the Migration

wrangler d1 execute drklynx-m-db-abc123def456 --remote \
  --file migrations/001_init.sql

Track Migrations

Keep a migrations/APPLIED.md:

# Applied Migrations

- 001_init.sql (2026-04-20 by you)

This prevents accidentally re-running migrations.

Backups & Data Retention

Cloudflare automatically retains full backups for 30 days. You can't manually trigger backups, but if you need your data restored, email support@drklynx.com with:

  • Your database ID
  • The date and time you want restored to
  • A brief reason

Restore usually takes 1–2 hours.

Quotas

Tier Soft Limit Hard Limit
Starter 5 GB 10 GB
Pro 25 GB 50 GB
Business 100 GB 200 GB
Enterprise 500 GB 1 TB

Soft limit: Warning email sent when exceeded. You can keep using the database, but performance may degrade.

Hard limit: New writes are rejected with an error. Contact support to upgrade.

Check your usage:

wrangler d1 info drklynx-m-db-abc123def456

Advanced: Exporting Your Database

To get a local copy of your database for development:

wrangler d1 backup download drklynx-m-db-abc123def456 > backup.sqlite3

This downloads a .sqlite3 file. Open it locally with any SQLite client:

sqlite3 backup.sqlite3
sqlite> SELECT * FROM users;

Performance Tips

  1. Index your frequently queried columns:

    CREATE INDEX idx_users_email ON users(email);
    
  2. Use prepared statements to avoid SQL injection:

    db.prepare('SELECT * FROM users WHERE id = ?').bind(userId).first()
    
  3. Avoid N+1 queries. Instead of:

    for (const user of users) {
      user.posts = db.prepare('SELECT * FROM posts WHERE user_id = ?').bind(user.id).all();
    }
    

    Do:

    const allPosts = db.prepare('SELECT * FROM posts').all();
    users.forEach(u => u.posts = allPosts.filter(p => p.user_id === u.id));
    
  4. Batch inserts:

    INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com'), ('Bob', 'bob@example.com');
    

Troubleshooting

"Database Not Found"

Make sure your database ID in wrangler.toml matches your drklynx-m-db-abc123def456.

"Permission Denied"

Your API token may be expired or scoped incorrectly. Check your credentials email or generate a new token at app.drklynx.com/microhost/<customer_id>.

"Timeout on Large Query"

If a query takes >30 seconds, it times out. Break it into smaller queries or add an index to speed it up.


What to Read Next


Getting help: Email support@drklynx.com or check status.drklynx.com.