[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-93317":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":15,"subscribersCount":15,"size":15,"stars1d":15,"stars7d":15,"stars30d":15,"stars90d":15,"forks30d":15,"starsTrendScore":15,"compositeScore":16,"rankGlobal":10,"rankLanguage":10,"license":10,"archived":17,"fork":17,"defaultBranch":18,"hasWiki":19,"hasPages":17,"topics":20,"createdAt":10,"pushedAt":10,"updatedAt":21,"readmeContent":22,"aiSummary":23,"trendingCount":15,"starSnapshotCount":15,"syncStatus":14,"lastSyncTime":24,"discoverSource":25},93317,"gorm-d1-adapter","intmian\u002Fgorm-d1-adapter","intmian","Make your Go-to-D1 connection 2–18× faster.","",null,"Go",110,3,2,0,38.81,false,"master",true,[],"2026-07-22 04:02:08","# gorm-d1-adapter\n\n[中文文档](README.zh-CN.md) · [Benchmarks](BENCHMARK.md) · [中文基准测试](BENCHMARK.zh-CN.md)\n\nA Cloudflare D1 adapter for GORM and `database\u002Fsql`. Make your Go-to-D1 connection **2–18× faster.**\n\n## Why This Exists\n\nD1 is practically free for low-traffic personal projects, but Cloudflare doesn't ship an official Go library. The original [gorm-driver-d1](https:\u002F\u002Fgithub.com\u002Fkofj\u002Fgorm-driver-d1) by kofj worked well enough, until the D1 API changed upstream and things broke. By then the repo had gone quiet — issues and PRs sat open with no response. I forked it as part of [mian_go_lib](https:\u002F\u002Fgithub.com\u002Fintmian\u002Fmian_go_lib\u002Ftree\u002Fmaster\u002Ffork\u002Fd1_gorm_adapter) to keep things patched, but the performance was hard to live with: single reads over 100ms, no real batch support, and the architecture made it difficult to fix either. Cloudflare themselves [recommend a Worker proxy](https:\u002F\u002Fdevelopers.cloudflare.com\u002Fd1\u002F) for external D1 access, so I started fresh. Full rewrite, Worker-first. This is the result.\n\nIf you used the old adapter: the migration path is straightforward. Both modes share the same GORM and `database\u002Fsql` interfaces, and REST mode is still around for compatibility.\n\n## Features\n\n- GORM and `database\u002Fsql` support.\n- **Worker Proxy is the recommended mode for production.** The Cloudflare REST API is still available for migration, fallback, and ops access.\n- Query, write, migrate, and batch operations.\n- Handles common data-type conversions between Go and D1 so you don't have to think about them.\n- Switch between REST and Worker modes through config — your application code doesn't change.\n\n## Worker Proxy\n\nPutting your Cloudflare Account API Token into every service is asking for trouble. Deploy the included D1 Worker Proxy instead. It runs inside Cloudflare, talks to D1 through the native binding, and your Go services only need a simple bearer token. You also get token auth, rate limiting, request IDs, and logs that redact SQL text and credentials.\n\nWorker's `env.DB.batch()` packs multiple statements into one edge request while keeping D1's native atomicity. Fewer round trips, same guarantees.\n\nREST mode remains available for existing integrations, migrations, and fallback. Both modes share identical GORM and `database\u002Fsql` usage — your code doesn't care which transport is underneath.\n\n## Project Layout\n\n```text\ngorm-d1-adapter\u002F\n├── config.go \u002F executor.go              Config and executor contracts\n├── driver.go \u002F connection.go            database\u002Fsql driver\n├── rest_executor.go \u002F rest_protocol.go  Cloudflare REST client\n├── worker_executor.go \u002F worker_protocol.go\n│                                         Worker Proxy client\n├── codec.go \u002F trace.go \u002F errors.go       Shared utilities\n├── gormd1\u002F                               GORM integration and migrator\n├── stdlib\u002F                               database\u002Fsql driver registration\n├── workers\u002Fd1-proxy\u002F                     Cloudflare Worker Proxy\n├── cmd\u002Fd1bench\u002F                          Benchmark tool\n└── scripts\u002F                              Validation and benchmark scripts\n```\n\n## Quick Start\n\n```bash\ngo get github.com\u002Fintmian\u002Fgorm-d1-adapter\n```\n\nCreate a `d1.Config`, pick your mode, and pass it to GORM:\n\n```go\ncfg := d1.Config{\n    Mode:           d1.ExecutorModeWorker,\n    WorkerEndpoint: \"https:\u002F\u002Fexample.workers.dev\",\n    WorkerToken:    \"\u003Ctoken>\",\n}\n\ndb, err := gorm.Open(gormd1.OpenConfig(cfg), &gorm.Config{})\n```\n\nWorker mode (the default) needs a deployed Worker endpoint and an access token. REST mode needs a Cloudflare Account ID, an Account API Token, and a D1 Database ID. Your application code stays the same either way.\n\n### REST Access\n\nUse an **Account API Token** with your account and database IDs. `BaseURL` is optional and defaults to `https:\u002F\u002Fapi.cloudflare.com\u002Fclient\u002Fv4`.\n\n```go\ncfg := d1.Config{\n    Mode:       d1.ExecutorModeREST,\n    AccountID:  \"\u003Ccloudflare-account-id>\",\n    APIToken:   \"\u003Ccloudflare-account-api-token>\",\n    DatabaseID: \"\u003Cd1-database-id>\",\n}\n\ndb, err := gorm.Open(gormd1.OpenConfig(cfg), &gorm.Config{})\n```\n\nSee [the Worker deployment guide](workers\u002Fd1-proxy\u002FREADME.md) and [the benchmark report](BENCHMARK.md) for more details.\n\n## What This Solves\n\n- Go services outside Cloudflare can use D1 without being rewritten for the Workers runtime.\n- Existing GORM or `database\u002Fsql` code can connect to D1 through familiar Go database interfaces.\n- The Cloudflare Account API Token stays behind the Worker binding — application services never touch it.\n- Multiple reads and writes combine into one atomic batch, reducing round trips and rolling back on failure.\n- Switch between Worker and REST transports without changing application code, for phased migration, legacy compatibility, and rollback.\n- GORM migrations are explicit about what's safe: creating tables, adding columns, and indexes are supported. Destructive DDL returns an explicit error.\n\n## Performance\n\nSame region, same D1 database, same container runtime. Worker Proxy isn't just a little faster — in some operations it's an order of magnitude ahead.\n\n**Connection open is ~18× faster** than REST and ~17× faster than the Legacy Adapter. The Worker's edge health check returns in ~11ms; REST token verification takes over 200ms round-tripping through Cloudflare's control plane. That difference alone makes Worker mode the obvious default.\n\n**Batch CRUD is ~6× faster.** Packing multiple statements into one `env.DB.batch()` call avoids per-statement round trips and keeps D1's native atomicity. REST batch tops out at ~450ms per op; Worker batch lands at ~72ms.\n\nEven single statements benefit — the Worker path is consistently 1.3× to 1.8× faster — but the real leverage is in batching and connection overhead.\n\n```mermaid\nxychart-beta\n    title \"Connection & Batch: Worker vs REST (lower is better)\"\n    x-axis [\"Open + Ping\", \"Batch CRUD\", \"Batch Select\"]\n    y-axis \"milliseconds\" 0 --> 500\n    bar \"REST\" [212, 451, 210]\n    bar \"Worker\" [11, 72, 63]\n```\n\n| Benchmark | REST | Worker | Gain |\n|---|---:|---:|---:|\n| GormOpenAndPing | 212.86 ms | 11.38 ms | **18.71×** |\n| ExecutorBatchCRUD | 450.56 ms | 71.65 ms | **6.29×** |\n| ExecutorBatchSelect | 209.60 ms | 63.15 ms | 3.32× |\n| GormSelectOne | 116.30 ms | 64.58 ms | 1.80× |\n| InsertOne | 121.51 ms | 70.65 ms | 1.72× |\n| DeleteOne | 132.25 ms | 81.70 ms | 1.62× |\n\nAll numbers from the same official run (`20260710-162100`): same region, same D1 database, `golang:1.25` Docker image, `10x` benchmark setting, 1100\u002F1100 correctness samples for each mode. The Legacy Adapter comparison (also 1.3×–1.8× on single ops, no true batch equivalent) is in [the full benchmark report](BENCHMARK.md), along with methodology and rerun instructions.\n\n## Compatibility & Limitations\n\n- The BLOB encoding uses the reserved prefix `d1b64:`. Worker mode decodes it as a BLOB. If your text happens to start with `d1b64:`, it will be read as binary. REST mode has no BLOB decoding layer — use Worker mode when you need reliable `[]byte` storage.\n- REST `APIToken` must be a Cloudflare Account API Token, verified against `\u002Faccounts\u002F{account_id}\u002Ftokens\u002Fverify`. User API Tokens (the `\u002Fuser\u002Ftokens\u002Fverify` variety) are not currently supported as REST credentials.\n- Booleans and timestamps are detected by column name: `flag`, `active`, and `is_*` columns are treated as booleans; columns containing `time` or ending in `_at` or `date` are parsed as RFC3339 timestamps. Other columns keep D1's raw type.\n- No interactive transactions. Worker batches use D1's native transactional batch API; REST batches use Cloudflare's native REST batch endpoint.\n- REST `BaseURL` and Worker `Endpoint` must include `http:\u002F\u002F` or `https:\u002F\u002F`. `database\u002Fsql.Ping` actually performs a verification call — REST checks the token endpoint, Worker hits the health endpoint. GORM calls Ping once when opening the database.\n- GORM migrations support creating tables, adding columns, and creating indexes. Altering or dropping columns and dynamically managing constraints return explicit unsupported errors.\n","这是一个为 Go 语言 GORM 和 database\u002Fsql 提供 Cloudflare D1 数据库高性能接入能力的适配器。它通过 Worker Proxy 模式（推荐）或 REST API 模式，实现 2–18 倍于旧版驱动的查询\u002F写入性能提升；支持批量操作、自动类型转换、数据库迁移，并统一抽象底层传输方式，使业务代码无需感知模式切换。适用于使用 Cloudflare D1 作为后端数据库的 Go Web 服务、Serverless 应用及轻量级全栈项目，尤其适合需兼顾安全性（避免泄露 API Token）、低延迟与兼容性的生产场景。","2026-07-16 02:30:05","CREATED_QUERY"]