Optimización de la velocidad de build de Astro: de 35 a 127 páginas/segundo
Optimización de la velocidad de build de Astro para sitios SSG grandes: 8 pasos aptos para principiantes llevaron un sitio de 339k páginas de 35 a 127 páginas por segundo. Sin cambiar a SSR.
Actualizado Publicado 35 min de lectura

¿Builds de Astro lentos? ¿Todo el mundo te dice que «simplemente pásate a SSR» para tu sitio grande? Esta guía de optimización de la velocidad de build de Astro explica cómo acelerar los builds de Astro manteniendo la generación de sitio estático (SSG), que tiene más sentido para la mayoría de los sitios grandes.
Las técnicas de este artículo llevaron un sitio SSG grande de 35 páginas/segundo a 127 páginas/segundo. Eso es una mejora de velocidad de 3,6x que redujo el tiempo de build de 9.642 segundos (2,7 horas) a 2.659 segundos (44 minutos). Funcionan para principiantes y no requieren cambiar a SSR.
Este artículo parte de un caso de estudio de Reddit: optimización de la velocidad de build de Astro de 9642s a 2659s. Si estás migrando un sitio de contenido grande de WordPress a Astro, estos pasos de optimización te ahorrarán horas de tiempo de build.
Lo que obtendrás de esta guía:
- Mejoras medibles en la velocidad de build (probadas en más de 339k páginas)
- Fragmentos de configuración listos para copiar y pegar que puedes aplicar esta misma noche
- Solución de problemas para errores de memoria (OOM), APIs lentas y tiempos de build inconsistentes
Antes de ver los pasos, aquí tienes algunos artículos relacionados sobre Astro:
- Crea tu blog de Astro gratis
- Añade vídeos de YouTube a tu blog de Astro
- Crea aplicaciones en tiempo real con Astro y Convex
- Despliega Astro y Convex en Vercel
Entendiendo SSG vs SSR
La diferencia entre la generación de sitio estático (SSG) y el renderizado en el servidor (SSR) importa a la hora de elegir un enfoque para tu proyecto.
Generación de sitio estático (SSG)
Las páginas se pregeneran durante el build y se sirven como archivos HTML estáticos.
Cómo funciona:
- Durante el build, Astro procesa tu contenido y tus componentes
- Genera archivos HTML estáticos para cada página
- Estos archivos los sirve directamente una CDN o un servidor web
- No se necesita procesamiento en el servidor para cada petición
Ventajas:
- Entrega rápida. Archivos servidos directamente desde la CDN.
- Económico. Se necesitan recursos de servidor mínimos.
- Resistente a picos de tráfico. Los archivos estáticos escalan sin cómputo adicional.
- Más seguro. Sin vulnerabilidades del lado del servidor.
- Buen SEO. Los motores de búsqueda indexan bien el contenido estático.
Desventajas:
- El tiempo de build crece a medida que aumentan las páginas
- La frescura de los datos depende de la frecuencia de rebuild
- Personalización limitada sin JavaScript
Renderizado en el servidor (SSR)
Las páginas se generan en cada petición (o se cachean con reglas inteligentes).
Cómo funciona:
- El usuario solicita una página
- El servidor procesa la petición en tiempo real
- Genera el HTML dinámicamente
- Envía la respuesta al usuario
Ventajas:
- Datos siempre frescos. El contenido está actualizado en cada petición.
- Personalización total. Se puede personalizar por usuario/petición.
- Primera página rápida. No hace falta un paso de build.
Desventajas:
- Costes más altos. Requiere capacidad de servidor para cada petición.
- Más lento bajo carga. Se necesita procesamiento en el servidor para cada petición.
- Vulnerable a la carga de rastreadores. Los bots pueden saturar tu servidor.
Por qué SSG suele ganar a SSR a gran escala
La idea clave del caso de estudio: «Nunca temes que un solo elemento reciba un millón de visitas en un día; temes que 100.000 elementos reciban 10 visitas en un día».
El problema de las arañas web
Los sitios web modernos soportan una carga enorme de rastreadores:
- Bots de motores de búsqueda (Google, Bing, etc.)
- Scrapers de entrenamiento de IA (ChatGPT, Claude, Perplexity, etc.)
- Herramientas de SEO y servicios de monitorización
- Bots scrapers
Números reales del caso de estudio:
- 2,3 millones de peticiones al día
- 774.860 visitantes únicos
- 710k URLs únicas solicitadas
- proporción de 30:1 de tráfico de arañas frente a tráfico humano
Con SSG, cada una de estas peticiones es un servicio de archivos barato. Con SSR, cada petición requiere capacidad de procesamiento del servidor.
Los rastreadores de IA no dejan de crecer
Los scrapers de IA de ChatGPT, Claude, Perplexity y otros aumentan la carga de arañas en los sitios web cada mes. Si usas SSR, este tráfico multiplica tus costes de servidor. Puedes bloquear los rastreadores de IA y reducir la carga de arañas con las reglas adecuadas. Para medir el impacto real en tu sitio, haz una prueba de carga con oha y observa los patrones de tráfico de rastreadores frente a humanos.
Cuánto cuesta
Configuración SSG (del caso de estudio):
- Servidor web de $29 + memcached + workers
- Servidor de base de datos de $29
- Servidor de build de $89
- Total: $147/mes
Esta configuración maneja 2,3M de peticiones diarias sin problemas, con una carga media inferior a 2 en un sistema de 8 núcleos.
Configuración SSR equivalente:
- Necesitaría varios servidores de aplicaciones potentes
- Pooling de conexiones de base de datos y capas de caché
- Balanceadores de carga y autoescalado
- Coste estimado: $500-2.000+/mes
Caso de estudio de rendimiento real
Este es el recorrido real de optimización del post de Reddit:
Estadísticas del sitio
- 349.734 archivos en total
- 346.236 páginas HTML
- 43 GB de tamaño total
- Build alimentado por API (sin archivos .md locales)
Evolución del rendimiento
| Etapa | Páginas generadas | Tiempo de build | Velocidad | Mejora |
|---|---|---|---|---|
| Inicial | 339.194 | 9.642s (2,7 horas) | ~35 páginas/seg | Referencia |
| Optimización intermedia | 339.251 | 3.583s (1 hora) | ~94 páginas/seg | 2,7x más rápido |
| Optimización final | 339.340 | 2.659s (44 minutos) | ~127 páginas/seg | 3,6x más rápido |
Fuente del caso de estudio
Estos números provienen de un sitio real en producción documentado en el hilo original de Reddit. El sitio obtiene todo el contenido de APIs, sin archivos markdown locales, lo que hace que las optimizaciones de caché y concurrencia sean especialmente impactantes.
Ahora veamos exactamente cómo consiguieron esta mejora.
Requisitos previos
Antes de empezar a optimizar, asegúrate de tener esto listo:
- Un proyecto Astro 7+ (o disposición a actualizar)
- Node.js ≥ 22.12 LTS — instala Node.js con NVM si aún no lo has hecho
- npm, pnpm o bun instalados
- Acceso al archivo
astro.config.mjs - Al menos 8 GB de RAM en la máquina de build (se recomiendan 16 GB+ para más de 10k páginas)
- Acceso SSH al servidor de build (si no compilas en local)
- Una forma de medir los builds: el comando
timeo el script de métricas de build que verás más adelante
8 pasos para optimizar tus builds de Astro
Estos ocho pasos aceleran los builds de Astro sin tocar tu contenido. Están ordenados por relación impacto/esfuerzo. Hazlos en secuencia para obtener los mejores resultados.
Paso 1: Actualiza Node.js y Astro
Esta es la mejora rápida de mayor impacto. Astro 7 incluye un compilador de .astro basado en Rust y Vite 8 con Rolldown. Ambos ofrecen mejoras medibles de velocidad de build respecto a versiones anteriores.
Astro 7 ya reduce los tiempos de build a la mitad en un sitio de 743 páginas solo con el compilador de Rust. Combinado con Node.js 22+ (que mejora la recolección de basura de V8 y la gestión de memoria), obtienes una mejora de base significativa.
# Check current versions
node --version
npm list astro
# Upgrade Node.js to latest LTS (22.12+)
nvm install 22
nvm use 22
# Upgrade Astro to latest 7.x
npm update astro
# If npm update fails with peer dependency conflicts:
npx @astrojs/upgradeVerificación: Ejecuta node --version (debería mostrar ≥ 22.12) y npm list astro (debería mostrar 7.x).
Modo de fallo: Si npm update astro falla por conflictos de dependencias entre pares, usa npx @astrojs/upgrade. La herramienta oficial de actualización de Astro gestiona las migraciones de forma limpia.
Si el tiempo de instalación de paquetes es tu cuello de botella, considera migrar Astro a Bun para instalaciones más rápidas.
Mejora esperada: ~30% de builds más rápidos solo por las mejoras de versión.
Paso 2: Aumenta la asignación de memoria de Node.js
Los builds grandes pueden alcanzar los límites de memoria, provocando pausas de recolección de basura y ralentizaciones. Cuando Node.js se queda corto de memoria heap, el recolector de basura mark-compact de V8 entra en acción y detiene todo el build.
# Method 1: Environment variable (recommended)
export NODE_OPTIONS="--max-old-space-size=8192"
# Method 2: Direct command
node --max-old-space-size=8192 ./node_modules/.bin/astro buildGuía de asignación de memoria:
- Sitios pequeños (< 1k páginas): 4 GB (4096)
- Sitios medianos (1k-10k páginas): 8 GB (8192)
- Sitios grandes (10k+ páginas): 16 GB+ (16384)
Verificación: Después de un build, ejecuta node -e "console.log(process.memoryUsage())" para comprobar el uso del heap. Debería estar muy por debajo de tu límite asignado.
Modo de fallo: Si ves «FATAL ERROR: Ineffective mark-compacts near heap limit», necesitas más memoria o menos concurrencia. Consulta la sección de solución de problemas más abajo.
Mejora esperada: Tiempo de build reducido y eliminación de los fallos relacionados con la memoria.
Paso 3: Optimiza la concurrencia del build
Astro puede procesar varias páginas simultáneamente, pero demasiada concurrencia causa contención de recursos. El punto óptimo depende del número de núcleos de tu CPU.
// astro.config.mjs
export default defineConfig({
build: {
concurrency: 4, // Start here, then test 2, 6, 8
},
});Metodología de prueba:
- Empieza con
concurrency: 2 - Ejecuta un build y mide el tiempo
- Aumenta a 4, luego a 6 y después a 8
- Usa el ajuste más rápido
Verificación: Ejecuta builds con concurrencia 2, 4, 6 y 8. Anota los tiempos y elige el más rápido. El caso de estudio encontró que 4 era lo óptimo en un sistema de 12 núcleos. Más no siempre es mejor.
Modo de fallo: Si los builds se cuelgan o fallan con concurrencia alta, reduce a 2 y ve subiendo. En runners de CI compartidos, empieza en 2.
Paso 4: Configura Vite y Rollup para velocidad
Nota sobre Astro 7 + Vite 8
Astro 7 incluye Vite 8 y Rolldown bajo el capó. La configuración siguiente funciona tanto con Rollup como con Rolldown, pero algunas claves específicas de Vite pueden comportarse de forma diferente. Consulta la documentación de Astro 7 para ver las notas de migración si actualizas desde Astro 6.
Vite se encarga del empaquetado y la optimización. Una configuración adecuada puede mejorar la velocidad de build.
Esta es la configuración optimizada del caso de estudio:
// astro.config.mjs
import { defineConfig } from "astro/config";
import { readFileSync } from "fs";
import { cpus } from "os";
const packageJson = JSON.parse(readFileSync("./package.json", "utf8"));
const CPU_COUNT = cpus().length;
export default defineConfig({
build: {
// Optimize concurrency for your CPU
concurrency: 4,
rollupOptions: {
// Maximum parallel file operations
maxParallelFileOps: CPU_COUNT * 3,
output: {
// Fewer, larger chunks = less overhead
manualChunks: undefined,
// Faster code generation
generatedCode: {
preset: 'es2022'
}
}
}
},
vite: {
build: {
// Allow larger chunks for speed
chunkSizeWarningLimit: 10000,
// Fastest minifier
minify: 'esbuild',
// Less transformation needed
target: 'es2022',
rollupOptions: {
maxParallelFileOps: CPU_COUNT * 3
}
},
esbuild: {
target: 'es2022',
// Fast minification settings
minifyIdentifiers: false, // Skip for speed
minifySyntax: true,
minifyWhitespace: true,
},
// Aggressive caching for faster subsequent builds
optimizeDeps: {
force: false // Use cache when possible
}
},
// Skip HTML compression for faster builds
compressHTML: false,
});Optimizaciones clave explicadas:
manualChunks: undefinedreduce la sobrecarga por fragmentación de chunkstarget: 'es2022'significa menos transpilación (objetivo moderno)minify: 'esbuild'es el minificador más rápido disponiblecompressHTML: falseomite la compresión para ganar velocidad. Deja que tu CDN se encargue de la compresión; la diferencia en la salida es despreciable.maxParallelFileOpsaprovecha todos los núcleos de CPU de forma eficiente
Verificación: Ejecuta time npm run build antes y después de aplicar la configuración. Compara el tiempo total de build y las páginas/seg.
Modo de fallo: Si aparecen avisos de chunkSizeWarningLimit, son informativos, no un fallo. Si ves errores de Rollup/Rolldown sobre manualChunks, consulta las notas de migración de Astro 7.
Paso 5: Implementa caché inteligente
Por qué importa: Si tu sitio obtiene datos de APIs (como hace el del caso de estudio para sus más de 339k páginas), la caché elimina peticiones de red redundantes. Esta es la mayor victoria individual para sitios SSG alimentados por API.
Si tu sitio Astro funciona con un CMS headless, la caché inteligente es la optimización de mayor impacto que puedes aplicar.
Aquí tienes una implementación de caché robusta:
// utils/fetchWithCache.js
import fs from 'fs';
import path from 'path';
import crypto from 'crypto';
export async function fetchWithCache(url, expirationSeconds = 600) {
const start = Date.now();
// Create unique cache filename
const urlHash = crypto.createHash('md5').update("cache_v1_" + url).digest('hex');
const cacheDir = path.join(process.cwd(), '.cache');
const cacheFile = path.join(cacheDir, `${urlHash}.json`);
// Ensure cache directory exists
if (!fs.existsSync(cacheDir)) {
fs.mkdirSync(cacheDir, { recursive: true });
}
// Check if cache file exists and is fresh
if (fs.existsSync(cacheFile)) {
const stats = fs.statSync(cacheFile);
const ageInSeconds = (Date.now() - stats.mtime.getTime()) / 1000;
if (ageInSeconds < expirationSeconds) {
const cachedData = JSON.parse(fs.readFileSync(cacheFile, 'utf8'));
console.log(`Cache hit: ${url} (${ageInSeconds.toFixed(1)}s old)`);
return cachedData;
}
}
// Fetch fresh data
console.log(`Fetching: ${url}`);
const response = await fetch(url, {
headers: {
'User-Agent': 'Astro Build Bot',
},
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = await response.json();
// Save to cache
fs.writeFileSync(cacheFile, JSON.stringify(data, null, 2));
console.log(`Fresh fetch completed: ${((Date.now() - start) / 1000).toFixed(2)}s`);
return data;
}Uso en tus páginas de Astro:
// pages/[...slug].astro
---
import { fetchWithCache } from '../utils/fetchWithCache.js';
export async function getStaticPaths() {
// Use cached fetch instead of regular fetch
const posts = await fetchWithCache('https://api.example.com/posts');
return posts.map(post => ({
params: { slug: post.slug },
props: { post }
}));
}
---Verificación: Después del primer build con caché, comprueba que existe el directorio .cache/ y que contiene archivos JSON. El segundo build debería ser significativamente más rápido: busca mensajes de «Cache hit» en la consola.
Modo de fallo: Si el contenido parece desactualizado, ejecuta rm -rf .cache y recompila. Ajusta expirationSeconds adecuadamente: 600 (10 minutos) es un buen valor por defecto.
Paso 6: Precalentamiento de caché (avanzado)
Por qué importa: Para sitios muy grandes con muchos endpoints de API, puedes precalentar la caché antes de que empiece el build principal. Salta este paso si tienes un sitio pequeño o menos de 5 endpoints de API: la caché básica del paso 5 lo gestiona bien.
Aquí tienes un script de Node.js para precalentar la caché:
// scripts/prewarmCache.js
import { fetchWithCache } from '../utils/fetchWithCache.js';
async function prewarmCache() {
console.log('Starting cache prewarming...');
// Define your API endpoints to prewarm
const endpoints = [
'https://api.example.com/posts',
'https://api.example.com/categories',
'https://api.example.com/authors',
// Add more endpoints as needed
];
// Warm cache with limited concurrency
const results = await Promise.allSettled(
endpoints.map(url => fetchWithCache(url, 3600)) // 1 hour cache
);
const successful = results.filter(r => r.status === 'fulfilled').length;
console.log(`Cache prewarming complete: ${successful}/${endpoints.length} successful`);
}
prewarmCache().catch(console.error);Ejecuta esto antes de tu build principal:
// package.json scripts
{
"scripts": {
"prewarm": "node scripts/prewarmCache.js",
"build": "npm run prewarm && astro build"
}
}Verificación: Ejecuta npm run prewarm por separado y comprueba que la consola muestra «Cache prewarming complete: X/Y successful».
Modo de fallo: Si el precalentamiento falla en algunos endpoints, comprueba la disponibilidad de la API y los límites de peticiones. El script usa Promise.allSettled, así que los fallos parciales no bloquean el build.
Paso 7: Considera un ramdisk (condicional)
Usuarios de NVMe: saltad este paso
Si tienes almacenamiento NVMe, el ramdisk aporta menos de un 1% de mejora. Este paso solo es útil para HDD o SSD SATA antiguos. Las unidades NVMe modernas son lo bastante rápidas como para que la sobrecarga de configuración no merezca la pena.
Cuándo ayuda: Solo con almacenamiento lento (discos mecánicos, SSD antiguos).
Cuándo no ayuda: Unidades NVMe modernas: la mejora suele ser inferior al 1%.
Cómo configurarlo (Linux/macOS):
# Create 4GB ramdisk
sudo mount -t tmpfs -o size=4g tmpfs /tmp/astro-build
# Build in ramdisk
cd /tmp/astro-build
# ... run your build here ...Verificación: Ejecuta df -h /tmp/astro-build para confirmar que el ramdisk está montado y tiene el tamaño correcto.
Modo de fallo: Si el build supera el tamaño del ramdisk, verás «No space left on device». Dimensiona el ramdisk con al menos el doble del tamaño de salida esperado.
Paso 8: Mejoras de hardware
Cuándo merece la pena: Solo si compilas varias veces al día y ya has hecho los pasos 1-7. Las mejoras de hardware tienen un ROI real, pero son la última palanca que tirar.
Lo que más importa:
- Rendimiento mononúcleo de la CPU: a Node.js le encantan los núcleos rápidos
- Caché de CPU (L3/L4): más caché = builds más rápidos
- Almacenamiento rápido: NVMe > SSD SATA > HDD
- RAM suficiente: evita el swapping a toda costa
Impacto del hardware en el caso de estudio:
- Antigua: Intel Xeon E5-1650 v3 → 3.583s de build
- Nueva: AMD Ryzen 9 5900X → 2.659s de build
- 25% de mejora solo por el cambio de CPU
Verificación: Ejecuta el mismo build en el hardware nuevo y compara con tu referencia.
Estrategias avanzadas de caché
Una vez que tengas funcionando la caché básica (paso 5), estas estrategias ayudan con sitios multi-API, actualizaciones frecuentes de contenido y builds de CI/CD.
Estrategia de invalidación de caché
La invalidación inteligente de caché garantiza datos frescos cuando se necesitan:
// utils/smartCache.js
export async function fetchWithSmartCache(url, options = {}) {
const {
maxAge = 600,
forceRefresh = false,
invalidateOn = []
} = options;
if (forceRefresh) {
return await fetchFresh(url);
}
// Check for invalidation conditions
for (const condition of invalidateOn) {
if (await condition()) {
console.log(`Cache invalidated for ${url}`);
return await fetchFresh(url);
}
}
return await fetchWithCache(url, maxAge);
}
// Usage with invalidation
const posts = await fetchWithSmartCache('https://api.example.com/posts', {
maxAge: 3600, // 1 hour
invalidateOn: [
() => process.env.FORCE_REFRESH === 'true',
() => Date.now() - lastDeployTime < 300000 // 5 minutes after deploy
]
});Optimización de peticiones por lotes
Minimiza las llamadas a la API agrupando las peticiones en lotes:
// utils/batchFetch.js
export async function batchFetchWithCache(urls, batchSize = 10) {
const results = [];
for (let i = 0; i < urls.length; i += batchSize) {
const batch = urls.slice(i, i + batchSize);
const batchResults = await Promise.allSettled(
batch.map(url => fetchWithCache(url))
);
results.push(...batchResults);
// Small delay to be nice to the API
if (i + batchSize < urls.length) {
await new Promise(resolve => setTimeout(resolve, 100));
}
}
return results;
}Verificación: Añade console.log(\Batch ${i}/${urls.length} complete`)` dentro del bucle para monitorizar el progreso en builds grandes.
Consideraciones de hardware
Antes de mejorar el hardware, haz un benchmark de tu servidor cloud para identificar el cuello de botella real: CPU, RAM o E/S de disco. No tiene sentido comprar más RAM si tus builds están limitados por la CPU.
Requisitos de CPU
| Tamaño del sitio | CPU recomendada | Núcleos | Caché |
|---|---|---|---|
| Pequeño (< 1k páginas) | Cualquier CPU moderna | 4+ | 8 MB+ |
| Mediano (1k-10k páginas) | Intel i7/AMD Ryzen 7 | 8+ | 16 MB+ |
| Grande (10k+ páginas) | Intel i9/AMD Ryzen 9 | 12+ | 32 MB+ |
| Enorme (100k+ páginas) | CPU de grado servidor | 16+ | 64 MB+ |
Requisitos de memoria
Cálculo base: ~2-4 MB por página en memoria durante el build.
| Tamaño del sitio | RAM mínima | Recomendada |
|---|---|---|
| Pequeño (< 1k páginas) | 8 GB | 16 GB |
| Mediano (1k-10k páginas) | 16 GB | 32 GB |
| Grande (10k+ páginas) | 32 GB | 64 GB |
| Enorme (100k+ páginas) | 64 GB | 128 GB+ |
Consideraciones de almacenamiento
Jerarquía de velocidad:
- NVMe Gen4: lo mejor para builds grandes
- NVMe Gen3: excelente para la mayoría de usos
- SSD SATA: mínimo recomendado
- HDD: solo con ramdisk
Recomendaciones de servidores de build
Para servidores de build asequibles con excelente rendimiento mononúcleo, Hetzner Cloud ofrece instancias de CPU dedicada desde ~8 €/mes. La línea CCX (AMD EPYC dedicado) es ideal para builds de Astro: obtienes rendimiento predecible sin vecinos ruidosos. Vultr es otra opción si necesitas regiones globales para pipelines de CI/CD distribuidos.
Los precios de los VPS subieron en general en 2026: si estás replanteándote una máquina alquilada, mira qué cambió y cuándo gana un mini PC.
Cuándo elegir SSG vs SSR
A veces SSR sí es la opción correcta. Aquí tienes un marco de decisión.
Si aún estás decidiendo el framework, consulta Astro vs Next.js vs TanStack Start: cuál gana en 2026 para una comparación detallada.
Matriz de decisión
| Factor | SSG | SSR | Híbrido |
|---|---|---|---|
| Frescura del contenido | Requiere rebuild | Siempre fresco | Mixta |
| Personalización | Limitada | Total | Por ruta |
| Rendimiento | Excelente | Variable | Excelente |
| Coste a escala | Muy bajo | Alto | Medio |
| Resistencia a rastreadores | Excelente | Baja | Buena |
| Complejidad de desarrollo | Simple | Compleja | Media |
Recomendaciones por caso de uso
Elige SSG cuando:
- El contenido no cambia con frecuencia (minutos/horas)
- Se espera mucho tráfico anónimo o de rastreadores
- Las limitaciones de presupuesto son importantes
- El máximo rendimiento es la prioridad
- Se prefiere un despliegue sencillo
Elige SSR cuando:
- Los datos en tiempo real son esenciales
- Se necesita mucha personalización
- El contenido generado por usuarios es lo principal
- Hay un número pequeño de páginas
- Los recursos de servidor no son un problema
Elige híbrido cuando:
- La mayoría del contenido es estático y una parte es dinámica
- Necesitas personalización en algunas rutas
- Quieres optimizar costes y rendimiento
- Puedes manejar complejidad a nivel de ruta
Ejemplo de implementación híbrida
// astro.config.mjs - Hybrid setup
export default defineConfig({
output: 'hybrid',
adapter: vercel(),
integrations: [
// Most pages are pre-rendered (SSG)
// Specific routes can opt into SSR
],
});// pages/dashboard/[user].astro - SSR route
---
export const prerender = false; // This page uses SSR
const { user } = Astro.params;
const userData = await fetch(`/api/user/${user}`);
---
<Layout title="Dashboard">
<UserDashboard data={userData} />
</Layout>Mitos comunes de optimización
Mito 1: "Más concurrencia siempre es mejor"
Realidad: La concurrencia tiene rendimientos decrecientes y puede causar contención de recursos. Más builds de páginas concurrentes significa más presión de memoria y más contención de CPU.
Pruébalo: Prueba valores de concurrencia de 2, 4, 6, 8 y 16. La mayoría de los sitios rinden mejor entre 2 y 6. El caso de estudio encontró que 4 era lo óptimo en un sistema de 12 núcleos.
Mito 2: "El ramdisk siempre acelera los builds"
Realidad: Solo ayuda con almacenamiento lento. Las unidades NVMe hacen que el ramdisk sea casi inútil: la mejora suele ser inferior al 1%.
Pruébalo: Mide tu build con y sin ramdisk en tu configuración de almacenamiento. Si usas NVMe, olvídate del ramdisk por completo.
Mito 3: "Necesitas SSR para sitios grandes"
Realidad: SSG puede manejar cientos de miles de páginas de forma eficiente con la optimización adecuada. El sitio del caso de estudio tiene más de 339k páginas y compila en menos de 45 minutos.
Evidencia: La proporción de 30:1 de tráfico de arañas frente a humanos significa que el servicio barato de archivos de SSG ahorra mucho más dinero que la flexibilidad por petición de SSR.
Mito 4: "El tiempo de build no importa en producción"
Realidad: Un tiempo de build de Astro más rápido significa despliegues más ágiles, actualizaciones de contenido más frecuentes, menores costes de CI/CD y una mejor experiencia de desarrollo. Si tu build tarda 2,7 horas, despliegas menos a menudo y reaccionas más lento a los cambios de contenido.
Mito 5: "La compresión de HTML siempre ahorra mucho espacio"
Realidad: Las CDN modernas gestionan la compresión (gzip, brotli) mejor que la compresión en tiempo de build. El compressHTML: true de Astro ralentiza los builds significativamente para un ahorro marginal de tamaño en la salida. Deja que tu CDN haga el trabajo.
Monitorización y medición del éxito
Sigue el tiempo de build de Astro a lo largo del tiempo para detectar regresiones pronto. Si tu build se vuelve más lento de repente, querrás saber exactamente qué dependencia o cambio de configuración lo causó.
Métricas de rendimiento del build
Sigue estas métricas para medir el éxito de la optimización:
// build-metrics.js
const startTime = Date.now();
export function logBuildMetrics(pageCount) {
const buildTime = (Date.now() - startTime) / 1000;
const pagesPerSecond = pageCount / buildTime;
console.log(`
📊 Build Metrics:
- Pages built: ${pageCount.toLocaleString()}
- Build time: ${buildTime.toFixed(1)}s
- Speed: ${pagesPerSecond.toFixed(1)} pages/sec
- Memory usage: ${process.memoryUsage().heapUsed / 1024 / 1024:.1f}MB
`);
}Integración con CI/CD
Sigue el rendimiento del build a lo largo del tiempo en tu pipeline de CI:
# .github/workflows/build-monitor.yml
name: Build Performance Monitor
on: [push, pull_request]
jobs:
build-perf:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: npm ci
- name: Build with timing
run: |
echo "BUILD_START=$(date +%s)" >> $GITHUB_ENV
npm run build
echo "BUILD_END=$(date +%s)" >> $GITHUB_ENV
- name: Report performance
run: |
BUILD_TIME=$((BUILD_END - BUILD_START))
echo "Build completed in ${BUILD_TIME} seconds"
# Send to your analytics/monitoring systemVerificación: Después de desplegar el workflow de monitorización, revisa los logs de GitHub Actions en busca de la salida «Build completed in X seconds» en el próximo push.
Modo de fallo: Si el build de GitHub Actions es mucho más lento que en local, comprueba las especificaciones de CPU/RAM del runner: los runners alojados por GitHub tienen 2 núcleos y 7 GB de RAM. Para sitios grandes, considera runners autoalojados.
Solución de problemas comunes
Diagnóstico rápido
Si tu build es lento, revisa esto en orden: (1) Versión de Node.js: ¿estás en 22.12+? (2) Asignación de memoria: ¿es --max-old-space-size lo bastante alto? (3) Ajuste de concurrencia: ¿has probado 2, 4, 6, 8? (4) Tasa de aciertos de caché: ¿está poblado .cache/? (5) Tiempos de respuesta de la API: ¿responden tus endpoints rápido?
Errores de falta de memoria
Síntomas:
FATAL ERROR: Ineffective mark-compacts near heap limit
JavaScript heap out of memorySoluciones:
- Aumenta
--max-old-space-size - Reduce la concurrencia del build
- Limpia la caché:
rm -rf .cache node_modules/.vite - Busca fugas de memoria en tu código
Respuestas lentas de la API
Síntomas:
- El build se cuelga en ciertas páginas
- Tiempos de build inconsistentes
- Errores de timeout de red
Soluciones:
- Implementa lógica de timeout y reintentos en las peticiones
- Usa la caché de forma agresiva
- Agrupa las peticiones de API en lotes cuando sea posible
- Considera los límites de peticiones de la API
// Robust fetch with retries
async function fetchWithRetry(url, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
const response = await fetch(url, {
timeout: 10000 // 10 second timeout
});
if (response.ok) return response;
if (i === retries - 1) throw new Error(`HTTP ${response.status}`);
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
} catch (error) {
if (i === retries - 1) throw error;
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}
}Tiempos de build inconsistentes
Síntomas:
- El tiempo de build varía significativamente entre ejecuciones
- Algunos builds son mucho más lentos que otros
Soluciones:
- Implementa una estrategia de caché consistente
- Comprueba la contención de recursos del sistema
- Monitoriza el uso de CPU/memoria durante los builds
- Usa versiones fijas para todas las dependencias
Conclusión y próximos pasos
Optimizar los builds de Astro para sitios SSG grandes es totalmente viable. El principio clave: SSG es eficiencia económica a escala. Cuando los rastreadores y los bots generan la mayor parte de tu tráfico, servir archivos pregenerados es mucho más rentable que procesar cada petición en el servidor.
Victorias rápidas: implementa esto primero:
- Actualiza Node.js (22.12+) y Astro (7.x)
- Aumenta la asignación de memoria según el tamaño de tu sitio
- Ajusta la concurrencia del build (empieza con 4)
- Configura Vite para velocidad (minificador esbuild, objetivo es2022)
Esfuerzo medio, alto impacto:
- Implementa caché inteligente para las llamadas a la API
- Optimiza tu
astro.config.mjscon la configuración completa del paso 4 - Monitoriza y mide el rendimiento del build a lo largo del tiempo
Optimizaciones avanzadas:
- Precalentamiento de caché para sitios muy grandes (más de 100k páginas)
- Mejoras de hardware si compilas con frecuencia
- Implementaciones de fetch personalizadas con lógica de reintentos
¿Quieres aprender más? Echa un vistazo a:
- Crea tu primer blog de Astro gratis
- Mejora tu blog con vídeos de YouTube
- Crea aplicaciones en tiempo real con Astro y Convex
- Despliega aplicaciones Astro en Vercel con Convex
El caso de estudio completo con logs y configuraciones detalladas está disponible en el hilo original de Reddit.


