Tu ejecutable ahora es una base de datos SQLite y corre igual
Un hola mundo en C, empaquetado como archivo SQLite de 1,7 MiB, se ejecuta nativamente en Linux sin cambio alguno. Farid Zakaria, ingeniero detrás del proyecto selfdb, demostró que el formato ELF —el que usa el kernel para cargar cada binario desde hace décadas— puede reemplazarse por una base de datos SQLite completa sin sacrificar rendimiento. La base de datos se convierte en el ejecutable.
El proyecto llamó la atención de Simon Willison y de la comunidad técnica porque introduce una idea provocadora: el formato ELF ya es una base de datos que se niega a admitirlo, con string interning manual, índices tipo bloom filter y tablas de secciones implementadas a mano. SQLite, en cambio, es un formato auto-descriptivo y estable desde hace más de dos décadas. ¿Qué pasa si se usa SQLite directamente como contenedor de un ejecutable?
Por qué un ELF parece una base de datos que se resiste a serlo
Zakaria, durante su doctorado, mappeó cada mecanismo de ELF a su equivalente en bases de datos:
👥 ¿Quieres ir más allá de la noticia?
En nuestra comunidad discutimos las tendencias, compartimos oportunidades y nos ayudamos entre emprendedores. Sin humo, solo acción.
👥 Unirme a la comunidad.strtaby.dynstrfuncionan como interning de strings..hashy.gnu.hashson índices estiloCREATE INDEX.- La tabla de cabeceras de sección equivale a
sqlite_schema, la tabla de tablas. sh_offsetysh_sizereproducen el layout de páginas b-tree.objcopy --strip-debugse reduce aDELETE+VACUUM.- El cache de
ldconfigydebuginfodson índices out-of-band.
Cada herramienta — readelf, nm, objcopy, ldconfig — reimplementa el mismo parser en serie. El formato es increíblemente terso, pensado cuando el espacio en disco escaseaba, explica Zakaria en su publicación del 23 de agosto. Modificarlo es frágil: hay que zerar secciones y añadir otras nuevas, sin un esquema que se autodescriba.
SELF: cuando SQLite se vuelve ejecutable
El formato que propone Zakaria se llama SELF (Structured Executable & Linkable Format) y se reduce a dos tablas obligatorias más algunas opcionales:
self_meta: cabecera ELF como pares clave/valor.segments: imagen de carga con un registro por cabecera de programa, con los bytes en unBLOB.symbols: tabla única de símbolos con versiones tipoGLIBC_2.2.5y un índice b-tree real.- Tablas opcionales para
sections,notes,dynamic_entries: borrarlas y el programa sigue corriendo.strip(1)se vuelve una transacción.
Para que el kernel acepte el archivo como ejecutable, SELF usa el campo application_id de 4 bytes que SQLite reserva en el offset 68 del header, estampado con el magic SELF (0x53454c46). Un SQLite común nunca matchea ese patrón.
Cómo el kernel aprende a ejecutar archivos SQLite
El truco se apoya en binfmt_misc, el subsistema de Linux para registrar binarios personalizados. Registrando el magic de SQLite más el SELF en el offset 68, el kernel lanza automáticamente el intérprete self-exec cada vez que ve un archivo con ese patrón.
En NixOS la configuración cabe en pocas líneas. En cualquier otra distribución, una variante del registro se reduce a:
printf '%s\n' ':self:M:68:SELF::/usr/local/bin/self-exec:' \
> /proc/sys/fs/binfmt_misc/register
self-exec es un programa en C enlazado contra libsqlite3 que lee los program headers y la tabla de símbolos desde la base de datos, mapea los segmentos en memoria, aplica relocaciones y salta al entry point. Funciona como ld.so, pero alimentado por queries.
Closures: binarios autosuficientes con SQL
La idea más potente no es ejecutar un archivo SELF suelto, sino empaquetar un binario y todas sus dependencias transitivas en un solo SQLite. La herramienta self closure toma un ejecutable y produce una base de datos con tablas objects y needs, donde resolved_path actúa como foreign key hacia la ruta exacta de cada librería.
El ejemplo de Zakaria con ls:
libgmp.so.10 rfabfsmwq02sn94mb3qg
libacl.so.1 x0zgiss9hdzcsll3cswg
libattr.so.1 08nfpyc4qhzdkc37nznv
libc.so.6 8kvxvr3pmsypxiypa4g8
Seis objetos, segmentos y todo, en un único archivo de 4,8 MiB. ldd se vuelve un JOIN.
Llevado al extremo, empaquetar los 723 ejecutables y 400 librerías distintas del PATH en una sola base de datos da como resultado 611,9 MiB, más pequeño que los 644,4 MiB de ELF originales según las cifras publicadas por Zakaria. 1.123 objetos, 346.386 símbolos y 3.808 aristas de dependencia, todo consultable con SELECT. Sin deduplicación explícita, en modo AppImage, esos mismos 723 programas pesarían 5,53 GiB.
El bonus inesperado: LD_PRELOAD transaccional
SELF incluye una tabla preload(ord, path) con los objetos a mapear al final, de modo que sus exports ganan. Activar o desactivar LD_PRELOAD es INSERT + DELETE dentro de una transacción —sin variables de entorno, sin relink, sin reinicio. Esto permite hacer cosas como interponer un malloc instrumentado en todo el userland y luego ROLLBACK para volver al estado anterior, algo imposible con la mecánica clásica.
Qué significa esto para tu startup
No se trata de migrar mañana a SELF. Se trata de tres ideas que sí puedes aplicar hoy:
- Inspecciona binarios con SQL en vez de
readelf+grep. La herramienta previa de Zakaria,sqlelf, expuesta en su paperarXiv:2405.03883, monta tablas virtuales sobre ELF. Sustituye pipelines frágiles de análisis por queries reproducibles. Útil para auditorías de dependencias y triage de supply chain. - Explora
binfmt_miscpara runtimes propios. El mecanismo que SELF usa para que el kernel lance SQLite es el mismo que Rust usa para.wasmo Java para.class. Si tu producto corre sobre un runtime custom, registrarlo enbinfmt_miscevita wrappers y scripts de shell en cada deploy. - Piensa en closures para artefactos reproducibles. El patrón SELF (un archivo, dependencias resueltas como FK, sin ambigüedad de
soname) es el mismo principio detrás de Nix store paths, OCI image layers y hasta debun build --compile. Cuando lances binarios a producción, replica el closure y evita el clásico "en mi máquina funciona" por una librería mal resuelta.
El coste de SELF hoy —según el benchmark publicado— es de unos 5 ms de overhead fijo para abrir la base de datos y arrancar el intérprete, más una copia proporcional a la imagen del programa. Los binarios stripped quedan dentro del 1 % del tamaño ELF original. No es un reemplazo para producción esta semana, pero sí la mejor evidencia de que el formato binario de Linux llevaba años pidiendo ser una base de datos.
Fuentes
- Simon Willison: Your executable is a SQLite database (fuente original del link post)
- Farid Zakaria: Your executable is a SQLite database (artículo primario de la investigación)
- fzakaria/selfdb en GitHub (código de SELF, self-exec y self-ld)
👥 ¿Quieres ir más allá de la noticia?
En nuestra comunidad discutimos las tendencias, compartimos oportunidades y nos ayudamos entre emprendedores. Sin humo, solo acción.
👥 Unirme a la comunidad














