# Deploying Hono on Cloudflare Workers

> Deploy a Hono API on Cloudflare Workers with wrangler dev, typed D1 bindings, and a tiny REST endpoint. The final post in the Bun and Hono series.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2026-08-10 | Topics: [Cloudflare](https://flaviocopes.com/tags/cloudflare/) | Canonical: https://flaviocopes.com/hono-cloudflare-workers/

This is the last post in my Bun and Hono mini-series. We started with [Bun](https://flaviocopes.com/bun/), looked at [Hono](https://flaviocopes.com/hono/) itself, then [middleware](https://flaviocopes.com/hono-middleware-cookies-headers/). Now we deploy.

If you've been following my [Cloudflare Workers](https://flaviocopes.com/cloudflare-workers/) series, you already know the platform. A Worker is a function that takes a request and returns a response. Hono is built for exactly that model.

## Why Hono on Workers

Hono was born on Cloudflare Workers. The name means "flame" in Japanese, and the project started as a tiny framework for the edge.

Workers give you a `fetch` handler. Hono gives you routing, middleware, and helpers on top of that same handler. No adapter, no glue code.

The whole library is small and fast. That's why it's my go-to when I need a small API on Cloudflare.

## Create the project

The Hono team ships a Cloudflare Workers template. Run the scaffolder:

```bash
npm create hono@latest my-api
```

When it asks for a template, pick `cloudflare-workers`. Or skip the prompt:

```bash
npm create hono@latest my-api -- --template cloudflare-workers
```

Move into the folder and install dependencies:

```bash
cd my-api
npm install
```

You get a minimal project. The entry point is `src/index.ts`:

```ts
import { Hono } from 'hono'

const app = new Hono()

app.get('/', (c) => {
  return c.text('Hello Hono!')
})

export default app
```

Hono exports the app directly. Cloudflare calls `app.fetch` under the hood.

The other important file is `wrangler.jsonc`:

```jsonc
{
  "$schema": "node_modules/wrangler/config-schema.json",
  "name": "my-api",
  "main": "src/index.ts",
  "compatibility_date": "2025-08-03"
}
```

That's your Worker config. Bindings for D1, KV, or R2 go here too.

## Run locally and deploy

The template wires up npm scripts for you. Start the local dev server:

```bash
npm run dev
```

That runs `wrangler dev`. Open `http://localhost:8787` and you'll see your hello message. Edit the code, save, and it reloads.

When you're ready to ship:

```bash
npm run deploy
```

Wrangler bundles your code and uploads it. You get a `*.workers.dev` URL in seconds. The first time, it opens a browser so you can log in to Cloudflare.

## Access bindings with types

On Workers, databases and storage show up on `env`. In Hono you read them from `c.env`.

Say you already created a D1 database and added it to `wrangler.jsonc`, like in my [Cloudflare D1](https://flaviocopes.com/cloudflare-d1/) post:

```jsonc
{
  "d1_databases": [
    {
      "binding": "DB",
      "database_name": "my-app-db",
      "database_id": "your-database-id"
    }
  ]
}
```

Pass the binding types to `Hono` as a generic:

```ts
type Bindings = {
  DB: D1Database
}

const app = new Hono<{ Bindings: Bindings }>()
```

Now `c.env.DB` is typed. You can also run `npm run cf-typegen` to generate types from your config automatically.

## A tiny posts API

Let's wire up two routes against a `posts` table. I won't re-explain D1 here — check the D1 post for migrations and schema setup.

Read all posts:

```ts
app.get('/api/posts', async (c) => {
  const { results } = await c.env.DB.prepare(
    'select * from posts order by created_at desc'
  ).all()

  return c.json(results)
})
```

Create a post:

```ts
app.post('/api/posts', async (c) => {
  const { title, body } = await c.req.json()

  await c.env.DB.prepare(
    'insert into posts (title, body, created_at) values (?, ?, ?)'
  ).bind(title, body, Date.now()).run()

  return c.json({ ok: true }, 201)
})
```

That's a real API. Routing, JSON parsing, and a database query — all in one file.

## Middleware and other bindings

Middleware works the same on Workers as anywhere else. Cookies, headers, CORS — everything from the [middleware post](https://flaviocopes.com/hono-middleware-cookies-headers/) applies here unchanged.

Other bindings work the same way. Add a KV namespace to `wrangler.jsonc`, type it on `Bindings`, and use `c.env.SESSIONS` (or whatever you named it). Same pattern for R2 buckets. I covered KV in a [separate post](https://flaviocopes.com/cloudflare-kv/).

## Wrapping up the series

We started with Bun as a fast runtime, learned Hono as a tiny web framework, explored middleware, and now we've deployed to the edge.

This is my preferred stack for small APIs on Cloudflare. Hono on Workers, D1 when I need SQL, KV when I need simple key lookups. Fast to scaffold, fast to deploy, fast at runtime.

If you want to go deeper, the [Hono Cloudflare Workers guide](https://hono.dev/docs/getting-started/cloudflare-workers) and the [Wrangler docs](https://developers.cloudflare.com/workers/wrangler/) are the next stop.
