En un proyecto personal empecé desplegando directamente a producción desde mi portátil. Funciona hasta el día en que un cambio rompe algo y no sabes cómo volver. En este capítulo monto lo que uso ahora: entornos separados, previews por rama, despliegue gradual y vuelta atrás en segundos.
Para quién es y qué necesitas
Para quien ya despliega a mano y quiere probar cambios sin miedo: entornos separados, previews por rama, despliegues graduales y vuelta atrás.
Antes de empezar:
- Un proyecto con Wrangler 4.135 o posterior (para Workers Previews).
- Un repositorio en GitHub o GitLab si quieres despliegues automáticos.
Al terminar tendrás producción y staging separados, una preview por rama protegida con Access, despliegues graduales y la vuelta atrás ensayada.
El recorrido de un cambio
flowchart LR
L[Local<br/>wrangler dev] --> PR[Preview por rama<br/>wrangler preview]
PR --> ST[Staging<br/>--env staging]
ST --> G[Producción gradual<br/>10 % → 100 %]
G -->|algo va mal| RB[wrangler rollback]
| Entorno | Para qué | Datos | Quién lo ve |
|---|---|---|---|
| Local | Desarrollar | Simulados en tu máquina | Tú |
| Preview (por rama) | Revisar un cambio concreto | Recursos propios de prueba | Tu equipo, con Access |
| Staging | Probar todo junto antes de publicar | Copia o datos de prueba | Tu equipo, con Access |
| Producción | Usuarios | Reales | Todo el mundo |
Para un proyecto personal, me basta con local + previews + producción. Staging lo añado cuando hay más de una persona o datos que importan.
Entornos con Wrangler
Un entorno es una copia del Worker con su propia configuración. Los recursos (D1, KV, R2) no se heredan: hay que declararlos en cada entorno, y deben ser distintos de los de producción.
{ "name": "notes", "main": "src/index.ts", "compatibility_date": "2026-11-03", "vars": { "ENVIRONMENT": "production" }, "d1_databases": [ { "binding": "DB", "database_name": "notes", "database_id": "…" } ], "routes": [{ "pattern": "notes.mydomain.dev", "custom_domain": true }], "env": { "staging": { "vars": { "ENVIRONMENT": "staging" }, "d1_databases": [ { "binding": "DB", "database_name": "notes-staging", "database_id": "…" } ], "routes": [ { "pattern": "staging.notes.mydomain.dev", "custom_domain": true } ] } }}npx wrangler deploy --env="" # production (the top level)npx wrangler deploy --env stagingnpx wrangler secret put STRIPE_KEY --env stagingnpx wrangler d1 migrations apply notes-staging --env staging --remoteCon entornos definidos, Wrangler avisa si despliegas sin --env. Para producción uso --env="": deja claro a qué entorno va cada despliegue, también en los scripts de package.json.
Previews por rama
Workers Previews crea, para cada rama, un entorno aislado bajo el mismo Worker, con su URL, variables, secretos, bindings y observabilidad. Se configura en el bloque previews (no hereda nada de producción):
{ "previews": { "vars": { "ENVIRONMENT": "preview" }, "d1_databases": [ { "binding": "DB", "database_name": "notes-preview", "database_id": "…" } ] }}npx wrangler preview # creates or updates the current branch's previewnpx wrangler preview delete --name my-branch # deletes itCada preview tiene dos URLs:
| URL | Qué sirve | Para qué |
|---|---|---|
<branch>-notes.<subdomain>.workers.dev |
El último despliegue de esa rama | Probar la rama |
<deployment-id>-notes.<subdomain>.workers.dev |
Un despliegue concreto, fijo | Enlazarlo en la revisión de un pull request |
| Recurso | ¿Aislado en la preview? |
|---|---|
| Durable Objects y Containers | Sí, automáticamente |
| D1, KV, R2 | Solo si declaras recursos distintos en previews |
| Workflows, rutas, Cron Triggers, consumidores de colas | No: apuntan a producción o no se crean |
| Service bindings | Llaman a la versión de producción del otro Worker |
Versiones y despliegue gradual
Cada wrangler deploy crea una versión y la pone al 100 %. Para cambios con riesgo, prefiero subir la versión sin publicarla y darle primero un porcentaje del tráfico:
npx wrangler versions upload # uploads the version, with no trafficnpx wrangler versions deploy # picks versions and percentages (10% / 90%)npx wrangler versions list # version historyMientras dura, el tráfico se reparte así:
flowchart LR
U[Usuarios] -->|90 %| V1[Versión actual]
U -->|10 %| V2[Versión nueva]
V2 -->|sin errores| T[100 % a la nueva]
V2 -->|errores| R[Vuelta a la actual]
Durante el despliegue gradual, la afinidad de versión mantiene a cada usuario en la misma versión, para que no salte entre la nueva y la antigua en cada clic. Si los errores no suben en el panel de observabilidad, paso al 100 %.
Volver atrás
npx wrangler rollback # to the previous versionnpx wrangler rollback <version-id> -m "reason" -y # to a specific oneLo probé en este mismo blog: los archivos estáticos vuelven con la versión y el cambio se nota en unos 10–15 segundos.
Despliegue automático: Workers Builds o GitHub Actions
| Workers Builds | GitHub Actions | |
|---|---|---|
| Configuración | Conectas el repositorio en el panel | Un archivo YAML en el repositorio |
| Previews por rama | Integradas | Con wrangler preview en el flujo |
| Minutos incluidos | 3.000 al mes (gratuito), 6.000 (pago) | Los de tu plan de GitHub |
| Cuándo | Lo más rápido para empezar | Si ya tienes pruebas y pasos propios en Actions |
name: Deployon: push: branches: [main]jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: { node-version: 22 } - run: npm ci - run: npm run check - run: npm test - run: npx wrangler d1 migrations apply notes --remote env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }} - run: npx wrangler deploy env: CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}Entornos de desarrollo protegidos con Access
Staging y previews no deberían ser visibles para nadie de fuera. Con Access (gratis hasta 50 usuarios) se protegen sin tocar el código:
- Zero Trust › Access › Applications › Add an application › Self-hosted.
- Dominios:
staging.notes.mydomain.devy*-notes.<subdomain>.workers.dev(todas las previews). - Política: Allow a los correos de tu equipo, con código por email o login de GitHub.
- En el Worker de staging, comprueba el JWT de Access como en el capítulo de seguridad.
Además, en los entornos que no son de producción, añado X-Robots-Tag: noindex a todas las respuestas: si un enlace se escapa, que al menos no acabe en Google.
Activar funciones poco a poco
Para cambios que no quieres atar a un despliegue (una función nueva solo para algunos usuarios, un porcentaje de tráfico), Cloudflare tiene Flagship, su servicio de feature flags con segmentación y porcentajes. En un proyecto pequeño me basta con una variable en KV; cuando hay varios flags y personas decidiendo, Flagship evita mantenerlo a mano.
Cuánto cuesta
Cuánto cuesta al mes
Supuestos: Producción, staging y previews por rama con D1 propia, desplegados con Workers Builds
| Concepto | Importe |
|---|---|
| Entornos y previewsSe cobra el uso (peticiones, datos), no los entornos | 0,00 $ |
| Workers Builds3.000 minutos al mes en gratuito; 6.000 en pago | 0,00 $ |
| AccessGratis hasta 50 usuarios | 0,00 $ |
| Total al mes | 0,00 $ |
Precios consultados el 3 de noviembre de 2026. Pueden cambiar.
| Límite | Gratuito | Pago |
|---|---|---|
| Previews por Worker | 100 | 500 |
| Despliegues por preview | 100 | 100 |
| Minutos de Workers Builds | 3.000 al mes, 1 build a la vez | 6.000 al mes, 6 a la vez; 0,005 $ por minuto extra |
Al llegar al límite de previews, Cloudflare borra la menos usada.
Resumen
- Cada despliegue es una versión;
wrangler rollbackvuelve en segundos (el código, no los datos). - Previews por rama con recursos propios, protegidas con Access.
- Despliegue gradual para los cambios con riesgo; CI con Workers Builds o GitHub Actions.
- Siguiente capítulo: cuándo no usar Cloudflare.
