SQLite en producción: patrones que han envejecido bien
Actualizado: 2026-05-03
SQLite lleva veinticinco años siendo la base de datos más desplegada del mundo, pero durante la mayor parte de ese tiempo se la consideró una opción de juguete para servidores. Esa percepción ha cambiado en los últimos tres años por una combinación de tres fuerzas: WAL maduro, discos NVMe generalizados en cualquier VPS barato, y proyectos como Litestream y libSQL que han resuelto las dos objeciones clásicas, la falta de replicación y la ausencia de acceso remoto. Este post recoge lo que funciona y lo que no después de varios años observándolo en producción.
Puntos clave
- El modo WAL cambia SQLite de forma tan profunda que hablar de SQLite-sin-WAL y SQLite-con-WAL como la misma base de datos induce a error: la diferencia de concurrencia es de dos órdenes de magnitud en cargas web típicas.
- Litestream transmite el WAL a un almacén de objetos compatible con S3 en tiempo casi real, lo que permite restauración a cualquier punto en el tiempo con pérdida máxima de pocos segundos.
- libSQL, el fork de SQLite mantenido por Turso, añade replicación embebida sincronizada para arquitecturas distribuidas geográficamente.
- SQLite cubre sin problema la mayoría de aplicaciones web con menos de mil usuarios concurrentes y bases por debajo de 100 GB.
- No aplica cuando la carga tiene escritura concurrente intensa, cuando se necesita acceso multi-servidor al mismo archivo, o cuando se requieren extensiones avanzadas de Postgres.
El modo WAL cambia todo
La diferencia entre SQLite con el modo por defecto de diario por rollback y SQLite con WAL activado es tan grande que hablar de ambas como la misma base de datos induce a error. El modo rollback serializa escrituras y lecturas en un único bloqueo de archivo, lo que limita la concurrencia útil a un puño de consultas por segundo. El modo WAL, escritura hacia adelante en un archivo separado, permite lecturas concurrentes mientras hay una escritura activa, y limita las colisiones a escritores simultáneos. Para aplicaciones web con relación 95 a 5 entre lecturas y escrituras, la diferencia de rendimiento es de dos órdenes de magnitud.
Activar WAL es una sola instrucción en tiempo de apertura de la base, pero tiene implicaciones que conviene conocer:
- El archivo WAL crece mientras hay transacciones activas y se compacta automáticamente cuando alcanza un umbral (por defecto mil páginas). En cargas con escrituras muy frecuentes conviene ajustar ese umbral hacia arriba.
- El archivo WAL y el archivo principal deben compartir sistema de archivos; intentar ponerlos en volúmenes distintos es un error clásico que rompe la atomicidad.
La segunda clave del rendimiento en servidor es ajustar el tamaño de página y la caché. SQLite usa páginas de 4 KB por defecto, que encaja bien con la mayoría de cargas, pero para tablas con filas pequeñas y muchas lecturas aleatorias, subir a 8 KB o 16 KB al crear la base puede mejorar la eficiencia de la caché del sistema de archivos.
Litestream y la replicación fue el punto de inflexión
El talón de Aquiles histórico de SQLite en servidor era la copia de seguridad. Hasta la llegada de Litestream en 2021, la única forma decente de respaldar una base activa era parar escrituras, copiar el archivo y reanudar. En cualquier sistema con tráfico real eso no es viable. Litestream resolvió el problema transmitiendo el WAL a un almacén de objetos como S3 en tiempo casi real, lo que permite restauración a cualquier punto en el tiempo con una pérdida máxima de pocos segundos.
Lo que empezó como un truco ingenioso se ha convertido en la pieza que hace viable SQLite en producción seria. En los proyectos desplegados, Litestream apuntando a un bucket S3 compatible como Hetzner Object Storage o Cloudflare R2 cuesta algunos céntimos al mes en almacenamiento y protege frente al fallo del disco o la destrucción del servidor. El proceso de restauración es un comando: descarga el estado del bucket, reconstruye la base al instante elegido y lanza la aplicación.
La evolución más reciente es libSQL, el fork de SQLite que mantiene Turso. Añadió replicación embebida sincronizada, permitiendo una base primaria en servidor y réplicas locales en cada cliente o en nodos regionales. Para aplicaciones distribuidas geográficamente, libSQL resuelve el problema de la lectura local sin tener que correr Postgres multi-región. La versión 1.0 estable de Turso Database llegó este otoño y ya se ve en despliegues de aplicaciones web con latencia crítica.
Cargas donde SQLite sigue siendo la mejor opción
SQLite en servidor con WAL y Litestream cubre sin pestañear la mayoría de aplicaciones web con menos de mil usuarios concurrentes y bases por debajo de 100 GB. Esto incluye muchos sistemas de gestión, paneles internos, sitios con contenido dinámico moderado, APIs de tamaño medio y prácticamente cualquier cosa que no sea una tienda con picos masivos o una red social con escritura intensiva. El caso de éxito más visible es el propio sqlite.org, que sirve su sitio entero desde una SQLite con varios millones de páginas vistas al mes.
El segundo nicho donde brilla es el desarrollo y las pruebas. Poder reemplazar Postgres por SQLite en el entorno de integración continua acelera el tiempo de arranque de los tests de decenas de segundos a menos de dos. La mayor parte del SQL estándar es compatible, y cuando algo se desvía se detecta pronto.
El tercer espacio es el de aplicaciones de escritorio y móvil que sincronizan con la nube. Con libSQL y su sincronización bidireccional el patrón de tener una base local en el cliente que replica con un servidor central se ha simplificado drásticamente.
Donde SQLite sigue siendo mala idea
Hay casos donde SQLite en servidor no compensa y conviene ser honesto:
- Carga con escritura concurrente intensa sostenida: SQLite serializa escritores por diseño. Un sistema con cientos de transacciones de escritura por segundo va a tocar techo. Postgres, MariaDB o incluso MySQL con InnoDB pueden absorber órdenes de magnitud más de escritura concurrente.
- Arquitectura multi-proceso con varios servidores de aplicación accediendo al mismo archivo: SQLite no está pensado para accesos por red al archivo. El bloqueo a través de NFS es poco fiable y ha sido fuente de corrupciones en proyectos reales. Si tu arquitectura requiere más de un servidor leyendo y escribiendo contra la misma base, SQLite no es la herramienta adecuada, punto.
- Necesidad de funciones avanzadas de Postgres: extensiones geoespaciales serias, búsqueda de texto completo de producción, o soporte transaccional para dos fases. La brecha con Postgres en estas áreas es sustancial.
Esta misma lógica de elegir la herramienta correcta para la carga correcta aplica al debate Citus para escalar Postgres horizontalmente: cada base de datos tiene su rango de fortalezas.
Cuándo compensa
La pregunta ya no es si SQLite puede sostener un servidor web, porque puede. La pregunta es si tu caso concreto encaja en su perfil de fortalezas. Si tu aplicación:
- Lee mucho más de lo que escribe.
- Cabe en un solo servidor.
- No necesita replicación síncrona multi-nodo.
- Valora la simplicidad operativa de un archivo sin proceso servidor.
Entonces SQLite con WAL y Litestream es probablemente la opción de menor coste total en ingeniería y operación.
Si por el contrario tu sistema crecerá a varios servidores, tendrá escritura concurrente alta, o ya tienes Postgres funcionando sin dolor, no hay razón para cambiar. La gracia de SQLite en 2025 no es que haya sustituido a Postgres, sino que ha dejado de ser una opción excéntrica para cierto rango de problemas. Ese rango es más grande de lo que mucha gente supone.
Conclusión
SQLite con WAL y Litestream puede ahorrar semanas de montaje de infraestructura que no aportan nada para un servicio que va a tener 200 usuarios activos al mes. Tomárselo en serio antes de asumir que necesitas una base de datos separada es parte de la ingeniería práctica.