Deployment

Database and File Storage

Configure production data services independently of the application host.

Choose the production database in cloud.config.ts. Without db.remote, Vercel uses Turso, while Cloudflare and Azure use D1. An explicit db.remote.provider overrides the host default, so you can keep the same database when moving hosts.

Local development continues to use SQLite and local files. Production requires the configured remote services; it never falls back to temporary local storage.

Use Turso on Vercel

Create a Turso database and obtain its URL and auth token. Add them to the ignored .env file or process environment:

TURSO_DATABASE_URL=libsql://your-database.turso.io
TURSO_AUTH_TOKEN=your-database-token

Turso is the default when deploy.target is vercel. To select it explicitly on any supported app host:

cloud.config.ts
db: {
  remote: { provider: 'turso' },
},

CloudConfig uses its libSQL adapter for Turso, applies SQL migrations, and uploads the credentials as server settings. It does not provision the Turso service or copy local development data. No Cloudflare account or Wrangler installation is needed for a project using Turso without Cloudflare services.

Both cloudconfig db status --remote and cloudconfig db migrate --remote follow the selected database. Override the credential names with db.remote.urlEnv and db.remote.tokenEnv when needed.

Use D1 from Vercel or Azure

On Cloudflare, the database driver uses the native D1 binding. On Vercel and Azure, it accesses the same database over HTTPS.

Select D1 explicitly before moving a Cloudflare app to Vercel, or when upgrading an existing Vercel app that used the previous D1 default:

cloud.config.ts
db: {
  remote: { provider: 'd1' },
},

Keep the existing Wrangler database ID and migrations. This retains the current database rather than selecting Vercel's new Turso default. An omitted provider continues to select D1 on Cloudflare and Azure.

Keep Wrangler installed for provisioning and migrations:

pnpm add -D wrangler

Add these server-only settings to the ignored .env file or process environment:

CLOUDFLARE_ACCOUNT_ID=your-account-id
CLOUDCONFIG_D1_API_TOKEN=your-d1-api-token

Create the token in Cloudflare → My Profile → API Tokens → Create Custom Token:

  1. Select Account → D1 → Edit.
  2. Include the account that owns the database.
  3. Set an expiry and plan how to rotate it.

Read permission alone cannot execute writes. This token grants account-level D1 access: keep it server-side, never in a public Nuxt or Next.js environment variable. CLOUDFLARE_API_TOKEN is accepted as a fallback.

The Wrangler file supplies the database name and ID. Existing databases are reused; a new one is provisioned after a successful build when needed. Wrangler OAuth can handle interactive provisioning, but its expiring login is not uploaded to the Node application.

Queries from another host use Cloudflare's REST API. Account API limits and an additional network round trip apply.

Keep an Existing R2 Bucket

Cloudflare uses the native R2 binding. For Vercel or Azure, supply bucket-scoped S3 credentials:

CLOUDCONFIG_STORAGE_ACCESS_KEY_ID=your-r2-access-key
CLOUDCONFIG_STORAGE_SECRET_ACCESS_KEY=your-r2-secret-key

CloudConfig derives the endpoint and bucket name from the account and Wrangler config, or deploy.r2. File metadata and authorization stay in CloudConfig.

Use an Existing libSQL Database

For another hosted libSQL service, select it independently of the app host:

cloud.config.ts
db: {
  remote: { provider: 'libsql' },
},

Supply its server credentials:

CLOUDCONFIG_DATABASE_URL=libsql://your-database.example.com
CLOUDCONFIG_DATABASE_TOKEN=your-database-token

The URL can use libsql:// or https://. Override the variable names with db.remote.urlEnv and db.remote.tokenEnv.

CloudConfig applies generated SQL migrations, checks drift, and records checksums in an atomic batch. Remote migration commands follow this setting:

pnpm exec cloudconfig db status --remote
pnpm exec cloudconfig db migrate --remote

The service must already exist. CloudConfig does not create it or import D1 rows. Changing providers requires an explicit data migration.

Other Database Engines

The built-in data stack currently supports SQLite-compatible databases: local SQLite, D1, Turso, and other libSQL services. Neon and Supabase require PostgreSQL support across schema compilation, queries, authentication, and migrations. PlanetScale also requires an adapter for its selected PostgreSQL or MySQL/Vitess engine. These providers are not supported yet.

Switching between SQLite-compatible providers reuses the schema and migrations; it does not move existing rows. A connection URL alone cannot convert SQLite migrations into PostgreSQL or MySQL migrations. Cosmos DB and AWS database services need adapters for the specific database engine or API.

Use an Existing S3-Compatible Bucket

Select S3 storage and your service's region:

cloud.config.ts
storage: {
  provider: 's3',
  region: 'your-region',
},

Supply the endpoint, bucket, and credentials:

CLOUDCONFIG_STORAGE_ENDPOINT=https://your-s3-endpoint.example.com
CLOUDCONFIG_STORAGE_BUCKET=blog-uploads
CLOUDCONFIG_STORAGE_ACCESS_KEY_ID=your-access-key
CLOUDCONFIG_STORAGE_SECRET_ACCESS_KEY=your-secret-key

The service and bucket must already exist. Selecting them does not copy files from another bucket.

Update an Older Mount

Newly generated standalone and Next.js mounts use configuredDatabase(config); the Nuxt module selects it automatically. Update older projects once:

pnpm add @cloudconfig/core@beta

In Nuxt projects, update @cloudconfig/nuxt@beta at the same time. In standalone and Next.js projects, replace an explicit sqliteFile() or d1() driver in the existing backend mount:

import { configuredDatabase } from '@cloudconfig/core/drivers/configured'

const app = createBackend(config, { db: configuredDatabase(config) })

Keep your existing config and createBackend imports. The configured driver uses db.local in development and the selected remote service in production.

Copyright © 2026