Si llegaste aquí buscando documentación de la integración @astrojs/db, en 2026 lo primero que hay que saber es esto: Astro DB se publicó como integración oficial en marzo de 2024, corrió unos dieciocho meses sobre Astro Studio (un fork de libSQL/Turso) y quedó deprecada cuando Astro Studio cerró en primavera de 2025. El paquete @astrojs/db aún se instala, pero el backend Studio alojado ya no existe. Astro 6 ya no lo entrega como add-on por defecto. El patrón híbrido descrito en esta guía sigue siendo válido; la capa de base de datos es ahora cualquier servicio SQL externo que conectes por tu cuenta.
Esta guía recorre el patrón WordPress + edge SQL con los runtime stores que los equipos españoles realmente despliegan en 2026: Turso (el fork libSQL que sobrevivió a Studio), Cloudflare D1, Neon Postgres y Supabase. WordPress sigue como backend editorial; una base de datos externa guarda los datos de runtime que el frontend necesita en el edge.
Si solo necesitas un frontend de WordPress más rápido, esta es la guía equivocada. Object cache más CDN lleva un sitio típico a TTFB inferior a 200 ms sin segunda base de datos. El patrón híbrido se gana su complejidad cuando el contenido editorial y los datos de runtime tienen formas genuinamente distintas, o cuando el lag de invalidación de caché del WP REST se convierte en una queja medible de la redacción.
Descubre más sobre desarrollo profesional WordPress en WPPoland.
RGPD y Schrems II: por qué la AEPD entra antes que el código
En el contexto español, la elección técnica entre Turso, D1, Neon y Supabase queda muchas veces en segundo plano frente a la evaluación de protección de datos. Datos personales en Astro DB o en cualquiera de sus sucesores significa: contrato de encargado de tratamiento al amparo del artículo 28 RGPD, evaluación Schrems II, medidas técnicas y organizativas documentadas y, en caso de duda, una Transfer Impact Assessment.
La AEPD ha publicado en taller propio criterios sobre transferencias internacionales que se alinean con la práctica europea tras Schrems II. Usar Cloudflare (Workers, D1, Pages) es viable, pero requiere DPA Cloudflare firmado, elección de región UE, y EIPD activa si los datos de runtime incluyen comentarios con nombre real, envíos de formularios de usuarios autenticados o estado de membresía. La exposición a la CLOUD Act de los proveedores estadounidenses es real y debe documentarse, no escamotearse.
Camino práctico que las agencias españolas siguen en 2026:
- WordPress alojado en España (Raiola Networks, SiteGround Madrid, OVH Estrasburgo en región UE). Los datos editoriales se quedan en territorio UE.
- Datos de runtime sin identificación personal (inventario, contadores, cachés): Cloudflare D1 o Turso, región UE, DPA firmado.
- Datos de runtime con identificación personal (comentarios, formularios, área de socios): Neon región UE, Supabase región UE, o Postgres en un proveedor español, porque la EIPD exige entonces bastante menos documentación de riesgo residual.
La migración de Astro DB a un store externo es, en clave Schrems II, también una oportunidad: el cambio obliga a inventariar qué datos están dónde. Es el momento adecuado para reescribir la EIPD desde cero en lugar de copiar la anterior.
Qué fue Astro DB realmente y qué lo sustituyó
Astro DB era una capa fina de TypeScript sobre libSQL, con definición de schema al estilo Drizzle (db/config.ts con defineDb, defineTable, column). El backend Studio ofrecía una instancia libSQL gestionada con plan gratuito de 1 GB de almacenamiento y alrededor de mil millones de lecturas de filas al mes. El desarrollo local corría contra un fichero SQLite, producción contra Studio.
Cuando Studio cerró, la migración oficial fue: mantener el schema db/config.ts, cambiar la connection string Studio por una URL libSQL o Turso autoalojada, actualizar el adapter. En Astro 6 el módulo virtual astro:db ya no aparece documentado como funcionalidad de primera clase. Las cuatro sustituciones realistas para 2026:
- Turso (libSQL, SQLite distribuido). Lo más cercano a la ergonomía original de Astro DB. El plan gratuito cubre sitios pequeños, lecturas replicadas en el edge.
- Cloudflare D1. SQLite sobre Workers. Límite de 1 MB por fila, 10 GB por base de datos en el plan de pago. Natural si ya despliegas en Cloudflare Pages o Workers.
- Neon. Postgres serverless con branch por PR. El compute del plan gratuito hace auto-pause, lo que se traduce en 2 a 4 segundos de cold start en la primera petición tras inactividad.
- Supabase. Postgres con Row Level Security y capa REST/GraphQL alojada. Más pesado que D1 o Turso, pero incluye auth de fábrica.
Los ejemplos de código mantienen la forma original astro:db porque sigue siendo el modelo mental más limpio. Donde la diferencia de runtime importa, la elección se nombra de forma explícita.
Cuándo el patrón híbrido se gana su complejidad
La mayoría de los sitios WordPress no deberían adoptarlo. Una instalación WP monolítica con object cache, capa de caché estática y CDN aguanta hasta unas 500 000 páginas vistas al mes antes de que el edge rendering cambie de forma medible la experiencia de usuario. Por debajo de ese umbral, el coste operativo de una segunda base de datos, una capa de sincronización y dos pipelines de despliegue supera la ganancia de latencia.
El patrón se gana cuando se cumple al menos una de estas condiciones:
- El frontend necesita datos estructurados que no encajan naturalmente en
wp_postsowp_postmeta: estado por usuario, inventario en tiempo real, leaderboards calculados, contadores de votación, envíos de formulario que no deberían volver a la base de datos WP. - Los objetivos de LCP o TTFB exigen edge rendering, y la redacción no abandona el panel WordPress.
- El lag de invalidación de caché WP REST (TTL de object cache de 300 a 600 segundos es el predeterminado en la mayor parte del hosting gestionado) es una queja recurrente de la redacción, y hace falta un segundo store que controles de extremo a extremo.
- El sitio ha cruzado el umbral de dolor del tiempo de build: 5000+ posts traídos del WP REST en build pueden llevar la build SSG de Astro a 20 o 30 minutos sin estrategia incremental.
Vision general de la arquitectura: Como funciona Astro DB + WordPress
Comprender la base arquitectonica permite tomar decisiones informadas sobre enfoques de implementación y estrategias de optimización.
El paradigma CMS hibrido
WordPress monolitico tradicional acopla la gestión de contenido con la presentacion. WordPress headless separa estas preocupaciones, exponiendo contenido via APIs. La arquitectura hibrida Astro DB agrega una tercera capa: bases de datos residentes en el edge que cachean y mejoran el contenido de WordPress.
Componentes arquitectonicos clave
| Componente | Propósito | Tecnologia |
|---|---|---|
| Backend WordPress | Creación de contenido, gestión de usuarios, medios | WordPress tradicional |
| Capa de sincronizacion | Transformación y propagacion de datos | Webhooks, REST API o GraphQL |
| Astro DB | Datos estructurados cacheados en el edge | LibSQL/Turso |
| Frontend Astro | Generación estatica + islas dinámicas | Framework Astro |
| CDN | Entrega global de contenido | Cloudflare, Vercel Edge, etc. |
Arquitectura del flujo de datos
┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐
│ WordPress │────▶│ Capa de │────▶│ Astro DB │
│ (Contenido) │ │ sincroniz. │ │ (Cache Edge) │
└─────────────────┘ └──────────────┘ └─────────────────┘
│
▼
┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐
│ HTML estatico │◀────│ Astro │◀────│ Consulta │
│ (Cache CDN) │ │ (Build) │ │ Edge │
└─────────────────┘ └──────────────┘ └─────────────────┘
Esta arquitectura elimina las llamadas directas a la base de datos de WordPress desde el frontend, mejorando dramaticamente los tiempos de respuesta mientras mantiene la frescura del contenido a través de revalidacion estrategica.
Guia de implementación: Construyendo tu sistema hibrido
Esta sección proporciona orientacion de implementación completa y lista para producción para conectar Astro DB con WordPress.
Fase 1: Configuración del backend WordPress
Paso 1: Instalar plugins requeridos
Instala plugins que expongan contenido estructurado via REST API con soporte de campos personalizados:
# Instalar Advanced Custom Fields Pro para contenido estructurado
wp plugin install advanced-custom-fields --activate
# Instalar WP GraphQL para obtencion eficiente de datos (opcional pero recomendado)
wp plugin install wp-graphql --activate
Paso 2: Configurar tipos de contenido personalizados
Define estructuras de contenido optimizadas para la sincronizacion con Astro DB:
// functions.php - Registrar tipo de contenido personalizado
function register_astro_content_type() {
register_post_type('astro_content', array(
'labels' => array(
'name' => 'Contenido Astro',
'singular_name' => 'Elemento de Contenido Astro'
),
'public' => true,
'show_in_rest' => true,
'rest_base' => 'astro-content',
'supports' => array('title', 'editor', 'custom-fields', 'thumbnail'),
'menu_icon' => 'dashicons-database'
));
}
add_action('init', 'register_astro_content_type');
Paso 3: Configurar disparadores de webhook
Configura WordPress para notificar a tu servicio de sincronizacion cuando cambie el contenido:
// Disparar sincronizacion al guardar post
function trigger_astro_sync($post_id) {
if (wp_is_post_revision($post_id)) return;
$post = get_post($post_id);
$webhook_url = getenv('ASTRO_SYNC_WEBHOOK');
wp_remote_post($webhook_url, array(
'body' => json_encode(array(
'post_id' => $post_id,
'post_type' => $post->post_type,
'action' => 'update'
)),
'headers' => array('Content-Type' => 'application/json')
));
}
add_action('save_post', 'trigger_astro_sync');
Fase 2: Configuración de Astro DB
Paso 1: Inicializar Astro DB
# Crear nuevo proyecto Astro con DB
npm create astro@latest mi-sitio-hibrido
cd mi-sitio-hibrido
npx astro add db
Paso 2: Definir esquema de base de datos
Crea db/config.ts con tablas que coincidan con tu estructura de contenido WordPress:
import { defineDb, defineTable, column } from 'astro:db';
const Posts = defineTable({
columns: {
id: column.number({ primaryKey: true }),
wpId: column.number({ unique: true }),
slug: column.text({ unique: true }),
title: column.text(),
content: column.text(),
excerpt: column.text({ optional: true }),
featuredImage: column.text({ optional: true }),
author: column.text(),
publishedAt: column.date(),
modifiedAt: column.date(),
categories: column.json(),
tags: column.json(),
meta: column.json({ optional: true }),
}
});
const Authors = defineTable({
columns: {
id: column.number({ primaryKey: true }),
wpId: column.number({ unique: true }),
name: column.text(),
email: column.text(),
avatar: column.text({ optional: true }),
bio: column.text({ optional: true }),
socialLinks: column.json({ optional: true }),
}
});
export default defineDb({
tables: { Posts, Authors }
});
Paso 3: Configurar conexión a la base de datos
Para producción, conecta a Turso para distribucion edge:
# Instalar Turso CLI
curl -sSfL https://get.tur.so/install.sh | bash
# Crear base de datos
turso db create wordpress-astro-hibrido
# Obtener URL de conexión
turso db show wordpress-astro-hibrido
# Establecer variables de entorno
export TURSO_DATABASE_URL="libsql://tu-db.turso.io"
export TURSO_AUTH_TOKEN="tu-token"
Fase 3: Implementación de la capa de sincronizacion
Crea una función serverless que sincronice contenido de WordPress a Astro DB:
// src/pages/api/sync.ts
import type { APIRoute } from 'astro';
import { db, Posts, Authors } from 'astro:db';
export const POST: APIRoute = async ({ request }) => {
const { post_id, post_type } = await request.json();
// Obtener de WordPress REST API
const wpResponse = await fetch(
`${import.meta.env.WP_API_URL}/wp-json/wp/v2/${post_type}/${post_id}`
);
const wpPost = await wpResponse.json();
// Transformar e insertar en Astro DB
await db.insert(Posts).values({
wpId: wpPost.id,
slug: wpPost.slug,
title: wpPost.title.rendered,
content: wpPost.content.rendered,
excerpt: wpPost.excerpt?.rendered,
featuredImage: wpPost.featured_media ?
await getFeaturedImage(wpPost.featured_media) : null,
author: wpPost.author,
publishedAt: new Date(wpPost.date),
modifiedAt: new Date(wpPost.modified),
categories: wpPost.categories,
tags: wpPost.tags,
}).onConflictDoUpdate({
target: Posts.wpId,
set: {
title: wpPost.title.rendered,
content: wpPost.content.rendered,
modifiedAt: new Date(wpPost.modified),
}
});
return new Response(JSON.stringify({ success: true }), {
status: 200,
headers: { 'Content-Type': 'application/json' }
});
};
Fase 4: Implementación del frontend
Generación de páginas estaticas con islas dinámicas
---
// src/pages/blog/[slug].astro
import { db, Posts, eq } from 'astro:db';
import CommentSection from '../../components/CommentSection.jsx';
export async function getStaticPaths() {
const posts = await db.select().from(Posts);
return posts.map(post => ({
params: { slug: post.slug },
props: { post }
}));
}
const { post } = Astro.props;
---
<article>
<header>
<h1>{post.title}</h1>
<time datetime={post.publishedAt.toISOString()}>
{post.publishedAt.toLocaleDateString()}
</time>
</header>
<div class="content" set:html={post.content} />
<!-- Isla dinamica para comentarios -->
<CommentSection postId={post.wpId} clientes:visible />
</article>
Estrategias de optimización del rendimiento
Configuración de cache en el edge
Configura tu CDN para un rendimiento optimo del hibrido Astro DB:
| Tipo de cache | Duracion | Estrategia |
|---|---|---|
| HTML estatico | 1 año | Inmutable con hash |
| Consultas Astro DB | 60 segundos | Stale-while-revalidate |
| Medios WordPress | 1 año | Largo plazo con cache-busting |
| Respuestas API | 5 minutos | Dinámico basado en tipo de contenido |
Optimización de consultas a la base de datos
// Usar indices para consultas comunes
// db/config.ts
const Posts = defineTable({
columns: {
// ... columnas
},
indexes: {
slugIdx: { on: ['slug'], unique: true },
publishedIdx: { on: ['publishedAt'] },
categoryIdx: { on: ['categories'] },
}
});
Regeneracion estatica incremental (ISR)
Implementa ISR para contenido que cambia frecuentemente:
// astro.config.mjs
export default defineConfig({
output: 'hybrid',
adapter: vercel(),
experimental: {
isr: {
// Regenerar páginas cada 60 segundos
expiration: 60,
// Omitir cache para usuarios autenticados
bypassToken: process.env.BYPASS_TOKEN,
}
}
});
Modos de fallo que de verdad hemos visto
Antes de las historias de éxito, el registro de averías. Son las formas que toma el dolor en migraciones reales, no hipótesis del tipo “qué pasaría si”.
Lag de invalidación de caché WP REST. El object cache de WordPress (Redis o Memcached) está, en la mayor parte del hosting gestionado, con TTL de 300 a 600 segundos. Si la capa de sincronización lee /wp-json/wp/v2/posts justo después de que la redacción publique, puede acabar sirviendo estado obsoleto en Astro DB hasta diez minutos. El remedio es invalidar el object cache desde el hook de publicación antes de que dispare el sync, lo que requiere hosting que permita llamar wp_cache_flush_group programáticamente.
Explosión del tiempo de build a escala. Un sitio de 20 000 posts tirando de todo desde WP REST en build SSG pasa 18 a 25 minutos solo en round-trips de red. Dos vías: pre-cargar datos en el runtime store (Turso/D1/Neon) en el webhook de publicación y dejar que Astro lea del store local en build, o pasar a build incremental de Astro con output: 'server' y renderizado on-demand para la long tail. El reflejo “todo SSG, siempre” se rompe a escala.
Límite de tamaño de fila de Cloudflare D1. D1 limita las filas individuales a 1 MB. Posts de WordPress con postmeta serializado o JSON renderizado de bloques Gutenberg pueden cruzar esa línea. Remedio: guardar el payload serializado en R2 (u otro object store) y dejar solo la referencia en D1. Descubrirlo un viernes por la tarde, cuando un post largo falla el sync, es desagradable.
Cold start de Neon. El plan gratuito de Neon (y el de pago más barato) hace auto-pause del compute tras inactividad. La primera query tras la pausa cuesta 2 a 4 segundos. Para una edge function que corre en cada petición, significa que el primer usuario tras 5 minutos de silencio ve un flash lento. O se paga compute always-on, o se acepta el cold start y se cachea agresivamente en el edge.
Una migración concreta: 20k posts, 50k comentarios, build de 18 minutos
Una publicación B2B española del sector legal tenía una instalación WP en un único servidor, alrededor de 20 000 posts y 50 000 comentarios de usuarios acumulados en una década. La redacción no se movía de WordPress; el equipo de ingeniería necesitaba TTFB por debajo de 100 ms desde Madrid y Barcelona y estaba cansado de pelear contra el plugin bloat.
La forma a la que llegaron:
- WordPress como CMS headless alojado en Raiola Networks, contenido tirado vía WP REST en el momento de la publicación, no en build. Un pequeño listener de webhook invalida el object cache y escribe registros normalizados en Cloudflare D1 (región UE).
- Comentarios trasladados por completo a D1. La tabla de comentarios WP quedó en archivo, los comentarios nuevos llegan al endpoint renderizado en el edge, persisten en D1, y un job nocturno los espeja de vuelta a WP para moderación editorial y comprobación de spam.
- Astro desplegado en Cloudflare Pages con
output: 'server'y reglas de caché agresivas. La mayoría de páginas renderizan en el edge desde D1 en 30 a 80 ms. - El tiempo de build pasó de 18 minutos (SSG completo con WP REST) a unos 3 minutos (Astro construye el esqueleto estático, el contenido dinámico se carga desde D1 en la primera petición y queda cacheado en el edge).
Los trade-offs aceptados: una segunda pipeline de despliegue, un script de sincronización que de vez en cuando necesita mimo cuando WP REST devuelve URLs de featured image rotas, y la restricción de 1 MB en D1 que obliga a externalizar un puñado de posts patológicamente largos. DPA con Cloudflare firmado, TIA documentada para la región UE de D1.
Comparación: WP monolítico frente al patrón híbrido
La comparación enfrenta una instalación WordPress monolítica competentemente configurada contra el patrón híbrido. El lado monolítico no es de paja: object cache, page cache, CDN, PHP moderno, hosting decente. Los números son el rango razonable a esperar, no garantía.
| Dimensión | WordPress monolítico (bien configurado) | Híbrido (WP + edge SQL) |
|---|---|---|
| TTFB en origen | típicamente 150 a 400 ms | 30 a 100 ms desde el edge |
| Tiempo hasta primer despliegue | minutos (sin paso de build) | 3 a 30 minutos según estrategia |
| Publicación editorial a producción | segundos (flush de caché) | 10 a 90 s (webhook + sync + invalidación) |
| Superficie operacional | un stack | dos stacks, una capa de sync |
| Esfuerzo RGPD | bajo en hosting español | DPA + TIA + EIPD para edge store externo |
| Forma del coste | factura de hosting escala con tráfico | hosting + edge DB + tráfico, presupuesto individual |
| Mejor encaje | hasta ~500 mil páginas vistas/mes | divergencia entre contenido y datos runtime, edge rendering como exigencia |
| Peor encaje | sitios que necesitan estado por usuario a escala | sitios de contenido pequeños con tráfico predecible |
Consideraciones de seguridad
Aislamiento de datos
- Panel de administración WordPress detras de VPN o restriccion de IP
- Astro DB usa credenciales separadas de WordPress
- Sin conexiónes directas a la base de datos desde el frontend
Seguridad de API
// Implementar limitacion de tasa en endpoints de sincronizacion
import { RateLimiter } from 'limiter';
const limiter = new RateLimiter({
tokensPerInterval: 10,
interval: 'minute'
});
export const POST: APIRoute = async ({ request }) => {
if (!await limiter.tryRemoveTokens(1)) {
return new Response('Limite de tasa excedido', { status: 429 });
}
// ... logica de sincronizacion
};
Validación de contenido
Siempre sanitiza el contenido de WordPress antes de almacenarlo en Astro DB:
import DOMPurify from 'isomorphic-dompurify';
const cleanContent = DOMPurify.sanitize(wpPost.content.rendered, {
ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'h2', 'h3', 'ul', 'ol', 'li', 'a'],
ALLOWED_ATTR: ['href', 'title', 'alt']
});
Solución de problemas comunes
Fallos de sincronizacion
| Sintoma | Causa | Solución |
|---|---|---|
| Contenido no se actualiza | Webhook no se dispara | Verificar logs de errores de WordPress |
| Sincronizacion parcial | Timeout de API | Implementar procesamiento por lotes |
| Desajuste de esquema | Conflicto de tipo de columna | Versionar tu capa de sincronizacion |
| Entradas duplicadas | Condicion de carrera | Usar restricciones de unicidad |
Degradacion del rendimiento
Monitorea estas metricas para identificar cuellos de botella:
// Agregar monitoreo de rendimiento
const start = performance.now();
const posts = await db.select().from(Posts);
console.log(`La consulta tomo ${performance.now() - start}ms`);
Artículos relacionados
- WordPress headless vs tradicional: Análisis ROI 2026
- WordPress REST API vs GraphQL 2026
- CI/CD WordPress Guia de automatizacion 2026
- Green Web y sostenibilidad digital
Cuándo no hacer esto
Saltarse el patrón híbrido es la decisión correcta más veces que adoptarlo. Si llevas un sitio de contenido, el tráfico está por debajo de medio millón de páginas vistas al mes y la redacción está cómoda en el panel WordPress: quédate en el monolito. Object cache, plugin de page cache y Cloudflare delante entregan el 90 por ciento de la ganancia de rendimiento sin segunda base de datos, sin capa de sync, sin la carga de on-call para dos sistemas. En hosting español gestionado, además, el asunto del RGPD queda fuera de la ecuación.
El patrón híbrido se gana cuando el contenido editorial y los datos de runtime tienen formas realmente distintas (votos, envíos, estado por usuario, inventario en tiempo real) o cuando los objetivos de LCP y TTFB exigen edge rendering y la redacción no se mueve. En adopción: elegir el runtime store según el destino de despliegue. Turso para ergonomía cercana al Astro DB original, Cloudflare D1 cuando ya usas Workers, Neon si la forma de los datos pide Postgres, Supabase cuando además se necesita auth y RLS. En datos personales: EIPD primero, código después. Astro DB como producto alojado dejó de ser una opción que puedas escoger en 2026.
Para apoyo en la implementación, trabaja con un especialista en desarrollo Astro que también te disuada de la arquitectura cuando no encaje. Contacta a WPPoland para una evaluación delimitada; precio por presupuesto individual.
Última actualización: 2026-04-01.


