How to Deploy OpenSEO on Cloudflare Workers and Manage D1 Database Backups
Deploy OpenSEO by using the Cloudflare "Deploy to Workers" button to provision a Worker, D1 database, and R2 bucket, then configure required secrets and protect your data with D1 export workflows before running maintenance operations.
OpenSEO is an open-source SEO analysis platform designed to run entirely on Cloudflare's edge infrastructure. Deploying OpenSEO on Cloudflare Workers involves binding serverless functions to a D1 SQLite database and R2 object storage, while proper database backup management ensures data integrity during schema migrations and content cleanup. This guide covers the complete deployment architecture and backup procedures implemented in the every-app/open-seo repository.
Initial Deployment Architecture
OpenSEO deploys as a Cloudflare Worker with two critical infrastructure dependencies: a D1 database named open-seo for relational data and an R2 bucket named open-seo for static assets and caching.
One-Click Worker Deployment
The fastest method to deploy OpenSEO uses Cloudflare's deploy button, which automatically creates all required resources. According to docs/SELF_HOSTING_CLOUDFLARE.md, this process provisions:
- A new Cloudflare Worker project
- A D1 database (
open-seo) for SQLite storage - An R2 bucket (
open-seo) for the DataForSEO cache and static files
After initial deployment, the wrangler.jsonc configuration file contains auto-generated resource IDs for your zone, D1 database, and R2 bucket. When updating your deployment, you must preserve this file: back up the current wrangler.jsonc, pull upstream changes, then restore your configuration before committing.
Required Secrets Configuration
Secure your deployment by adding three mandatory secrets through the Cloudflare dashboard (Workers & Pages → your Worker → Settings → Variables & Secrets):
POLICY_AUDandTEAM_DOMAIN: Enable Cloudflare Access authentication, restricting the dashboard to your organization's identity providerDATAFORSEO_API_KEY: Authenticates requests to the external SEO data provider API
Database Backup Strategy for OpenSEO D1
Because OpenSEO uses Cloudflare D1 (a managed SQLite database), backups are essential before any destructive database operations, such as running the default-project cleanup script.
Manual D1 Export Procedures
Before executing maintenance commands, create a backup using the Wrangler CLI:
# Export D1 database to JSON format
wrangler d1 export open-seo > backup-$(date +%F).json
The docs/default-project-cleanup.md file explicitly recommends taking a D1 backup or creating a "time-travel restore point" via the Cloudflare dashboard before applying changes.
Pre-Cleanup Safety Checks
The cleanup command includes built-in safety mechanisms. When running:
pnpm cleanup:default-projects:d1 --database open-seo --apply --confirm-remote-apply
The script automatically checks for a recent D1 backup and aborts if none is detected. Always run a dry run first to preview affected rows:
pnpm cleanup:default-projects:d1 --database open-seo
Automated Backup Workflows
The wrangler.jsonc file already declares a cron trigger running every 15 minutes (*/15 * * * *). You can extend this to automate backups by adding a script that exports the D1 database and stores the result in R2:
// Add to wrangler.jsonc triggers configuration
"triggers": {
"crons": ["*/15 * * * *"]
}
For automated long-term retention, schedule a command that pipes wrangler d1 export output directly to your R2 backup bucket.
R2 Storage Lifecycle Management
OpenSEO caches DataForSEO API responses under the dataforseo-cache/ prefix in R2. Without lifecycle rules, this cache grows indefinitely.
Configure automatic expiration to delete cached responses older than 7 days:
npx wrangler r2 bucket lifecycle add open-seo dataforseo-cache-expiry \
--prefix dataforseo-cache/ \
--expire-days 7
This rule prevents unbounded storage growth while maintaining recent cache hits for performance.
Key Configuration Files
Understanding these source files helps troubleshoot deployment and backup issues:
wrangler.jsonc: Defines Worker bindings (D1, R2), cron triggers, and resource IDs located at the repository rootdrizzle.config.ts: Configures the Drizzle ORM for D1 migrations used during deploymentscripts/cleanup-default-projects.sql: Contains the SQL executed by the cleanup command; review this before running destructive operationssrc/server.ts: Worker entry point that initializes D1 and R2 connections using theenvbindings defined inwrangler.jsonc
Summary
Deploying OpenSEO on Cloudflare Workers requires provisioning three components: a Worker instance, a D1 database, and an R2 bucket. Key operational practices include:
- Preserving
wrangler.jsoncresource IDs during updates to maintain infrastructure bindings - Configuring
POLICY_AUD,TEAM_DOMAIN, andDATAFORSEO_API_KEYsecrets for security and API access - Always exporting D1 backups before running
cleanup:default-projects:d1with the--applyflag - Implementing R2 lifecycle rules to automatically purge cached SEO data older than 7 days
- Utilizing the existing 15-minute cron trigger in
wrangler.jsoncfor automated backup scheduling
Frequently Asked Questions
What infrastructure does OpenSEO require on Cloudflare?
OpenSEO requires three Cloudflare resources: a Worker (compute), a D1 database named open-seo (SQLite storage), and an R2 bucket named open-seo (object storage). The "Deploy to Cloudflare" button creates these automatically, as documented in docs/SELF_HOSTING_CLOUDFLARE.md.
How do I back up the OpenSEO database before maintenance?
Export your D1 database using wrangler d1 export open-seo > backup-$(date +%F).json before any destructive operations. The cleanup script enforces this by checking for recent backups before allowing --confirm-remote-apply execution.
Why does the R2 bucket need lifecycle configuration?
OpenSEO caches DataForSEO API responses under the dataforseo-cache/ prefix. Without lifecycle rules, storage costs grow indefinitely. Configure a 7-day expiration rule to automatically remove stale cache entries while preserving recent data.
How do I update OpenSEO without losing my configuration?
When pulling updates from the every-app/open-seo repository, copy your existing wrangler.jsonc to a temporary location first. After merging upstream changes, restore your original wrangler.jsonc to preserve your D1 database ID, R2 bucket ID, and other Cloudflare resource bindings.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →