Prisma Doesn't Support JSON Columns in Cloudflare D1
While experimenting with Pylon (a GraphQL framework that runs on Cloudflare Workers) in a hobby project, I connected it to a Cloudflare D1 database and ran Prisma’s introspection command to generate the schema:
npx prisma db pull
It pulled in about 15 tables correctly. But the output included a batch of warnings I almost missed:
Warning: These fields are not supported by Prisma Client, because Prisma currently
does not support their types:
- Model "end_users", field "features", original data type: "jsonb"
- Model "end_users", field "metadata", original data type: "json"
- Model "organizations", field "settings", original data type: "json"
D1 is SQLite-based, and SQLite does support storing JSON (it even has JSON functions like json_extract and json_each). D1 extends this with json and jsonb column type annotations. The actual stored value is text, but the type annotation signals intent.
Prisma does not map these types. The fields are generated in the schema file with Unsupported():
model end_users {
id String @id
features Unsupported("jsonb")?
metadata Unsupported("json")?
}
Any field marked Unsupported is excluded from the generated Prisma Client. You cannot read or write those fields through Prisma. They’re invisible to your application code as far as Prisma is concerned.
The Workaround
Store JSON as TEXT and handle serialization manually:
model end_users {
id String @id
features String? // JSON string
metadata String? // JSON string
}
In your application:
const user = await prisma.end_users.findUnique({ where: { id } });
const features = JSON.parse(user.features ?? "{}");
When writing:
await prisma.end_users.update({
where: { id },
data: { features: JSON.stringify(newFeatures) },
});
It’s not elegant, but it works. You lose the type annotation in the database, but since D1 is SQLite under the hood, the actual storage format is the same — a text column containing a JSON string.
Migration Workflow
If you’re generating migrations for D1, the workflow is:
# Generate a SQL migration from schema diff
npx prisma migrate diff \
--from-empty \
--to-schema-datamodel prisma/schema.prisma \
--script \
--output migrations/0001_init.sql
# Apply locally
wrangler d1 migrations apply <database-name> --local
# Apply remotely
wrangler d1 migrations apply <database-name> --remote
The --from-empty flag treats the current database as empty, so you get a full CREATE TABLE migration. Use --from-schema-datasource to diff against the actual live database for incremental migrations.
Status as of 2024
This is a known limitation. There’s an open Prisma GitHub issue tracking JSON type support for SQLite-based databases. If your schema has a lot of JSON columns, Prisma over D1 may not be the right combination. An alternative is to use Drizzle ORM, which handles D1’s JSON columns natively and gives you proper TypeScript types for them.