⏱️ Lectura: 11 min
Durante años, guardar datos de forma persistente dentro de una aplicación web significó depender de IndexedDB, un almacén de pares clave-valor lento y con una API incómoda. Eso cambió con SQLite WebAssembly OPFS: la combinación de SQLite compilado a WebAssembly y el Origin Private File System (OPFS) del navegador, que permite crear bases de datos SQL reales con acceso a disco casi nativo, sin servidor.
📑 En este artículo
El resultado es que aplicaciones web pueden ahora ejecutar consultas SQL completas —con índices, transacciones y joins— directamente en el cliente, y persistir esos datos en un archivo real dentro del sandbox del navegador.
TL;DR
- OPFS llegó a Chromium en 2022 y después a Firefox y Safari, dando acceso sincrónico a archivos desde Web Workers.
- El proyecto oficial SQLite Wasm incluye un VFS que escribe la base de datos en OPFS, evitando la lentitud de IndexedDB.
- wa-sqlite, de Roy Hashimoto, es una implementación alternativa con varios VFS optimizados para distintos casos de uso.
- El acceso sincrónico a OPFS solo funciona dentro de un Web Worker, no en el hilo principal del navegador.
- El VFS con acceso desde el hilo principal requiere cabeceras COOP/COEP y SharedArrayBuffer habilitado en el sitio.
- Esta arquitectura impulsa el software local-first: apps que funcionan offline y sincronizan datos cuando hay red.
- Drizzle ORM y kysely ya soportan drivers para SQLite Wasm con OPFS, facilitando su uso en producción.
Qué pasó
El equipo de SQLite, en colaboración con ingenieros de Google Chrome, publicó una build oficial de SQLite compilado a WebAssembly que incluye soporte nativo para OPFS como backend de almacenamiento. En paralelo, la comunidad open source —con proyectos como wa-sqlite de Roy Hashimoto— desarrolló implementaciones alternativas que exploran distintas estrategias de acceso a disco dentro del navegador.
La novedad central es que, por primera vez, una aplicación web puede abrir un archivo .sqlite real, escribirlo página por página igual que lo haría SQLite en un sistema operativo de escritorio, y mantenerlo persistente entre sesiones sin depender de IndexedDB ni de sincronización constante con un servidor.
Contexto e historia
Antes de OPFS, los navegadores solo ofrecían dos formas de persistencia del lado del cliente: localStorage, limitado a pocos megabytes y con una API síncrona bloqueante, e IndexedDB, una base de datos NoSQL asíncrona pensada para pares clave-valor, no para consultas SQL relacionales.
Proyectos como sql.js —una de las primeras compilaciones de SQLite a WebAssembly, basada en Emscripten— permitieron ejecutar SQL en el navegador desde hace años, pero con una limitación importante: la base de datos vivía completamente en memoria. Para persistirla había que serializar el archivo completo a un array de bytes y guardarlo en IndexedDB, un proceso costoso que se volvía inviable con bases de datos de varios megabytes.
El Origin Private File System resolvió ese cuello de botella. Es una API del estándar File System Access que expone, para cada origen web, un sistema de archivos privado y aislado del sistema operativo del usuario. La pieza clave es FileSystemSyncAccessHandle, que permite operaciones de lectura y escritura sincrónicas —algo que el resto de las APIs web evita deliberadamente para no bloquear el hilo principal—. Esta sincronía solo se permite dentro de un Web Worker, precisamente para no congelar la interfaz de usuario.
Cómo funciona SQLite WebAssembly OPFS
La arquitectura típica de una aplicación que usa SQLite WebAssembly OPFS separa el trabajo en tres capas. El hilo principal maneja la interfaz de usuario y nunca toca el disco directamente. Un Web Worker carga el módulo WASM de SQLite y expone una API asíncrona —vía postMessage o Comlink— hacia el hilo principal. Dentro de ese worker, el VFS personalizado de OPFS traduce cada operación de SQLite (leer una página de 4 KB, escribir el journal, hacer fsync) en llamadas sincrónicas sobre FileSystemSyncAccessHandle.
SQLite Wasm ofrece, en su build oficial, dos variantes de VFS sobre OPFS con distintos compromisos entre velocidad y flexibilidad:
- OPFS VFS — permite acceso concurrente desde múltiples pestañas y coordina el acceso mediante
SharedArrayBufferyAtomics.wait, lo que exige que el sitio se sirva con cabecerasCross-Origin-Opener-PolicyyCross-Origin-Embedder-Policy. - OPFS SyncAccessHandle Pool VFS — mantiene un grupo fijo de manejadores de archivo abiertos por adelantado, evitando la sobrecarga de abrir y cerrar archivos en cada operación; a cambio, solo admite una pestaña activa a la vez sobre la misma base de datos.
El siguiente fragmento muestra la inicialización típica del cliente oficial dentro de un worker:
// worker.js
import sqlite3InitModule from '@sqlite.org/sqlite-wasm';
const sqlite3 = await sqlite3InitModule();
const db = new sqlite3.oo1.OpfsDb('/mydb.sqlite3');
db.exec(`
CREATE TABLE IF NOT EXISTS notas (
id INTEGER PRIMARY KEY,
texto TEXT NOT NULL,
creada_en INTEGER DEFAULT (unixepoch())
);
INSERT INTO notas (texto) VALUES ('Primera nota persistida en OPFS');
`);
const filas = db.selectObjects('SELECT * FROM notas ORDER BY creada_en DESC');
console.log(filas);
Ese archivo mydb.sqlite3 queda escrito en el sistema de archivos privado del origen: sobrevive a recargas de página, cierres del navegador y reinicios del sistema operativo, exactamente igual que un archivo SQLite en disco.
graph LR
A["Hilo principal / UI"] -->|postMessage| B["Web Worker"]
B --> C["SQLite compilado a WASM"]
C --> D["VFS OPFS (SyncAccessHandle)"]
D --> E["Origin Private File System"]
E --> F["Disco del usuario"]
Datos y cifras
El salto de rendimiento frente al enfoque anterior basado en IndexedDB es el argumento central detrás de la adopción de SQLite WebAssembly OPFS. Serializar y deserializar una base de datos completa en cada escritura —como hacía sql.js sin OPFS— tiene un costo que crece con el tamaño del archivo: una base de datos de varias decenas de megabytes puede tardar segundos enteros en guardarse, algo inviable para una aplicación interactiva.
Con el VFS de OPFS, en cambio, cada operación de SQLite se traduce en una escritura de página (típicamente 4 KB) directamente sobre el archivo en disco, sin reserializar la base completa. La documentación oficial del proyecto SQLite describe esta diferencia como el motivo principal por el cual el rendimiento se acerca al de SQLite ejecutándose de forma nativa en Node.js o en una aplicación de escritorio, en lugar de comportarse como una base de datos puramente en memoria.
Otro dato relevante es el soporte de navegadores: OPFS con createSyncAccessHandle está disponible en los navegadores basados en Chromium, en Firefox y en Safari desde sus versiones publicadas en 2022 y 2023, lo que significa que, a diferencia de muchas APIs web nuevas, la cobertura entre navegadores modernos de escritorio es prácticamente universal, con matices todavía en algunos entornos móviles.
💭 Clave: la ganancia de rendimiento no viene de que WebAssembly sea más rápido que JavaScript per se, sino de que OPFS permite operaciones de archivo sincrónicas y a nivel de página, evitando la reserialización completa de la base de datos en cada escritura.
Impacto y análisis
La disponibilidad de una base de datos SQL real y persistente dentro del navegador tiene implicaciones directas para el diseño de aplicaciones web. El patrón conocido como local-first —popularizado por proyectos de investigación como Ink & Switch— propone que la aplicación trabaje siempre contra una copia local de los datos, y que la sincronización con el servidor quede como una capa opcional en lugar de un requisito para cada interacción.
SQLite WebAssembly OPFS encaja naturalmente en ese patrón: una aplicación de notas, un editor colaborativo o una herramienta de análisis de datos puede ejecutar consultas SQL completas sin latencia de red, funcionar completamente offline, y sincronizar cambios cuando la conexión vuelve a estar disponible. Esto reduce la dependencia de infraestructura de backend para operaciones que antes requerían un viaje de ida y vuelta al servidor por cada consulta.
El ecosistema de herramientas alrededor de este enfoque también está madurando. ORMs como Drizzle y kysely ya incluyen drivers específicos para SQLite Wasm, y motores de sincronización dedicados —pensados para reconciliar cambios entre la copia local en OPFS y una base de datos remota— empiezan a aparecer como categoría propia dentro del ecosistema de herramientas para desarrolladores web. En paralelo, proyectos que compilan motores más pesados, como PostgreSQL, a WebAssembly muestran que la tendencia de mover motores de base de datos completos al cliente no se limita a SQLite.
⚠️ Ojo: OPFS es un almacenamiento por origen, no un archivo accesible desde el sistema operativo del usuario ni sincronizado automáticamente entre dispositivos; si el usuario borra los datos del sitio o usa otro navegador, la base de datos local desaparece o queda vacía.
Qué sigue
Los puntos abiertos giran alrededor de la ergonomía y la concurrencia. El modelo actual, donde el acceso sincrónico a OPFS solo es posible dentro de un worker, obliga a los desarrolladores a diseñar su aplicación alrededor de mensajería asíncrona entre el hilo principal y el worker, algo que añade complejidad comparado con simplemente llamar a una función de base de datos de forma directa.
También se espera que continúe la adopción de cabeceras COOP/COEP en más sitios, un requisito que durante años fue un obstáculo para adoptar SharedArrayBuffer por las restricciones impuestas tras las vulnerabilidades tipo Spectre. A medida que más frameworks documenten cómo configurar esas cabeceras de forma sencilla, la barrera de entrada para usar SQLite WebAssembly OPFS en producción debería seguir bajando.
Finalmente, es previsible que sigan apareciendo capas de sincronización de más alto nivel construidas sobre esta base: en vez de que cada equipo resuelva desde cero cómo reconciliar la copia local en OPFS con el servidor, es probable que se consoliden algunas soluciones estándar, de forma similar a como ocurrió con los ORMs para bases de datos tradicionales.
💡 Tip: si vas a experimentar con SQLite WebAssembly OPFS, empezá con la build oficial de sqlite.org antes de evaluar alternativas como wa-sqlite: tiene mejor documentación y sigue de cerca los releases del propio SQLite.
📖 Resumen en Telegram: Ver resumen
Preguntas frecuentes
¿Qué es OPFS?
OPFS (Origin Private File System) es una API del estándar File System Access que le da a cada origen web un sistema de archivos privado, aislado del resto del sistema operativo del usuario, con soporte para operaciones de lectura y escritura sincrónicas dentro de un Web Worker.
¿SQLite WebAssembly OPFS reemplaza a IndexedDB?
No necesariamente. IndexedDB sigue siendo útil para almacenamiento simple de pares clave-valor. SQLite WebAssembly OPFS tiene sentido cuando la aplicación necesita consultas SQL relacionales, transacciones o índices sobre datos estructurados.
¿Funciona en todos los navegadores?
Los navegadores basados en Chromium, Firefox y Safari soportan OPFS con acceso sincrónico desde sus versiones publicadas en 2022 y 2023, aunque conviene verificar el comportamiento exacto en dispositivos móviles antes de depender de esta funcionalidad en producción.
¿Es necesario usar un Web Worker?
Sí, para el acceso sincrónico completo a través de FileSystemSyncAccessHandle. Ejecutar SQLite en el hilo principal sin worker evita bloquear la interfaz, pero renuncia a la variante más rápida del VFS de OPFS.
¿Los datos se sincronizan entre dispositivos?
No de forma automática. OPFS almacena los datos localmente por origen y por navegador; sincronizar entre dispositivos requiere una capa adicional que reconcilie la copia local con un servidor remoto.
¿Cuál es la diferencia entre la build oficial de SQLite y wa-sqlite?
La build oficial vive dentro del propio repositorio de SQLite y sigue de cerca cada release del motor. wa-sqlite es un proyecto independiente de Roy Hashimoto que explora implementaciones de VFS adicionales y suele incorporar experimentos antes que la build oficial.
Referencias
- Documentación oficial de SQLite Wasm — explica los distintos VFS disponibles sobre OPFS y cómo inicializar la base de datos.
- MDN: Origin Private File System — referencia de la API y sus restricciones de acceso sincrónico desde workers.
- wa-sqlite en GitHub — implementación independiente de SQLite compilado a WebAssembly con múltiples VFS.
📱 ¿Te gusta este contenido? Únete a nuestro canal de Telegram @programacion donde publicamos a diario lo más relevante de tecnología, IA y desarrollo. Resúmenes rápidos, contenido fresco todos los días.
0 Comentarios