Friendly Go client for Cloudflare D1 over the official Cloudflare HTTP API.
d1http is not a GORM driver and not a database/sql driver. It is a small, direct HTTP client that gives you full control over D1 requests, metadata, retries, import/export, and management APIs.
go get github.com/pubflow/d1httppackage main
import (
"context"
"fmt"
"os"
"github.com/pubflow/d1http"
)
func main() {
ctx := context.Background()
d1 := d1http.New(d1http.Config{
AccountID: os.Getenv("CLOUDFLARE_ACCOUNT_ID"),
DatabaseID: os.Getenv("D1_DATABASE_ID"),
APIToken: os.Getenv("CLOUDFLARE_API_TOKEN"),
})
_, err := d1.Exec(ctx, `
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY,
email TEXT NOT NULL
)
`)
if err != nil {
panic(err)
}
_, err = d1.Exec(ctx, "INSERT INTO users (id, email) VALUES (?, ?)", 1, "hello@example.com")
if err != nil {
panic(err)
}
rows, err := d1.Raw(ctx, "SELECT id, email FROM users WHERE id = ?", 1)
if err != nil {
panic(err)
}
fmt.Println(rows[0].Maps())
}- Database management: list, get, create, update, patch, delete.
- Query APIs:
/rawviaRaw,RawIn,BatchRaw./queryviaQuery,QueryIn,BatchQuery.
- Import SQL files.
- Export databases.
- Time travel bookmark and restore.
- User-token and account-token verification.
- Structured Cloudflare API errors.
- Retry support for
429and5xx. - D1 metadata preserved: rows read, rows written, duration, served-by region/colo, DB size.
client := d1http.New(d1http.Config{
AccountID: "...",
DatabaseID: "...", // optional for management APIs, required for simple query helpers
APIToken: "...",
Retry: d1http.RetryConfig{
MaxRetries: 3,
},
})For request-level timeouts, use context:
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
_, err := client.Raw(ctx, "SELECT 1")Use Raw for performance-sensitive paths. It returns rows as arrays:
results, err := client.Raw(ctx, "SELECT id, email FROM users")
fmt.Println(results[0].Results.Columns)
fmt.Println(results[0].Results.Rows)Use Query for friendlier object-shaped rows:
results, err := client.Query(ctx, "SELECT id, email FROM users")
fmt.Println(results[0].Results[0]["email"])D1 accepts multiple SQL statements in one request. BatchRaw joins statements and flattens params:
results, err := client.BatchRaw(ctx, []d1http.Statement{
{SQL: "INSERT INTO users (id, email) VALUES (?, ?)", Params: []any{1, "a@example.com"}},
{SQL: "SELECT * FROM users WHERE id = ?", Params: []any{1}},
})data, err := os.ReadFile("dump.sql")
if err != nil {
panic(err)
}
res, err := client.ImportSQL(ctx, "", data, 2*time.Second)
if err != nil {
panic(err)
}
fmt.Println(res.Status)res, err := client.ExportUntilComplete(ctx, "", d1http.ExportRequest{
OutputFormat: "polling",
}, 2*time.Second)
if err != nil {
panic(err)
}
fmt.Println(res.Result.SignedURL)