> ## Documentation Index
> Fetch the complete documentation index at: https://docs.edgespark.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Use the EdgeSpark database

> Define Drizzle schema in your EdgeSpark repo, generate migrations, and query your Cloudflare D1 database with the runtime SDK.

Every EdgeSpark project includes a [Cloudflare D1](https://developers.cloudflare.com/d1/) database. You define your app tables in `server/src/defs/db_schema.ts`, generate migrations with the CLI, and query the database from the runtime SDK.

## Define your schema

Add app tables to `server/src/defs/db_schema.ts`:

```typescript server/src/defs/db_schema.ts theme={null}
import { integer, sqliteTable, text } from "drizzle-orm/sqlite-core";

export const posts = sqliteTable("posts", {
  id: integer("id").primaryKey({ autoIncrement: true }),
  title: text("title").notNull(),
  content: text("content"),
  authorId: text("author_id").notNull(),
  createdAt: text("created_at").notNull().default("(datetime('now'))"),
});
```

If you need relations, add them in `server/src/defs/db_relations.ts`.

## Generate and apply migrations

After editing `db_schema.ts`, run:

```bash theme={null}
edgespark db generate
edgespark db migrate
```

Useful related commands:

```bash theme={null}
edgespark db generate --name add_posts
edgespark db check
edgespark db studio
```

<Tip>
  Use `edgespark pull schema` only for platform-managed tables that EdgeSpark generates into `server/src/__generated__/`. Your app tables live in `server/src/defs/` and use the migration workflow above.
</Tip>

## Query data

Use the runtime SDK inside route handlers:

```typescript server/src/index.ts theme={null}
import { db } from "edgespark";
import { auth } from "edgespark/http";
import { desc, eq } from "drizzle-orm";
import { Hono } from "hono";
import { posts } from "@defs";

const app = new Hono()
  .get("/api/posts", async (c) => {
    const rows = await db
      .select()
      .from(posts)
      .orderBy(desc(posts.createdAt));

    return c.json(rows);
  })
  .get("/api/posts/:id", async (c) => {
    const id = Number(c.req.param("id"));
    const [post] = await db.select().from(posts).where(eq(posts.id, id));

    if (!post) return c.json({ error: "Not found" }, 404);
    return c.json(post);
  })
  .post("/api/posts", async (c) => {
    const body = await c.req.json<{ title: string; content?: string }>();

    const [post] = await db
      .insert(posts)
      .values({
        title: body.title,
        content: body.content ?? null,
        authorId: auth.user.id,
      })
      .returning();

    return c.json(post, 201);
  });

export default app;
```

## Update and delete data

```typescript server/src/index.ts theme={null}
import { db } from "edgespark";
import { auth } from "edgespark/http";
import { eq } from "drizzle-orm";
import { Hono } from "hono";
import { posts } from "@defs";

const app = new Hono()
  .patch("/api/posts/:id", async (c) => {
    const id = Number(c.req.param("id"));
    const body = await c.req.json<{ title?: string; content?: string }>();

    const [post] = await db
      .update(posts)
      .set(body)
      .where(eq(posts.id, id))
      .returning();

    return c.json(post);
  })
  .delete("/api/posts/:id", async (c) => {
    const id = Number(c.req.param("id"));

    await db
      .delete(posts)
      .where(eq(posts.id, id))
      .returning({ authorId: posts.authorId });

    return c.body(null, 204);
  });

export default app;
```

## Run ad-hoc SQL

For inspection or one-off data changes, use:

```bash theme={null}
edgespark db sql "SELECT * FROM posts"
edgespark db sql "DELETE FROM posts WHERE id = 42" --confirm-dangerous
```

## Constraints

<Warning>
  Runtime DDL is blocked. Do not use `edgespark db sql` for `CREATE TABLE`, `ALTER TABLE`, or `DROP TABLE`. Apply schema changes through `edgespark db generate` and `edgespark db migrate`.
</Warning>

Transactions are not available. Use `db.batch([...])` for atomic multi-step operations, and see [platform limits](/reference/limits) whenever you are working near database or bundle constraints.

## See also

<Columns cols={2}>
  <Card title="db reference" icon="code" href="/sdk/database">
    Complete API for selects, inserts, updates, deletes, relational queries, and batching.
  </Card>

  <Card title="Declarative workflow" icon="database" href="/agents/declarative-workflow">
    How schema files, generated types, and migrations stay in sync.
  </Card>
</Columns>
