Queryable Executables
I was pleasantly surprised and happy to see that my article ‘Your executable is a SQLite database’ resonated with people. It is a format I have been thinking about for a while, and the idea seems to have struck a chord with others. A quick recap: SELF, a format where the program is a SQLite database. We can use binfmt_misc to trigger a custom interpreter that maps the rows in the segments table and jumps to the entry point, and a whole class of binary tooling collapses into SQL. What keeps surprising me is how having the file format be a SQLite database keeps collapsing everything into SQL. One idea that was immediately evident to myself and others through comments: If the executable is a database, and a database is something you can write to, can the running program use it to also store its state? 🤔 Yes! 🤯 We can collapse not only a complete distribution but all the state for every application into a single file, alleviating the need for /var/ or /tmp/ or /home/ or any other filesystem. The program can store its own state in the same file it is running from, and it can do so transactionally. self-httpd is a proof-of-concept webserver that does exactly that. It is a single file program executed from a database. The file contains the program, the website, the routes and all the visitor logs. All state is updated in the same SQLite file as the program itself. # Our server is a single file, and it is a SQLite database $ file server server: SQLite 3.x database, application id 1397050438, ... $ ./server --journal wal 8080 self-httpd: serving 3 routes out of /srv/self/server self-httpd: listening on http://0.0.0.0:8080 with 4 workers $ curl -s localhost:8080 | head -1 # nobody has pressed the button on that page yet $ sqlite3 server 'SELECT count() FROM presses' 0 $ curl -s -X POST -d press localhost:8080/api/press {"presses":1,"button":"press"} # the application data is inside the same database $ sqlite3 server 'SELECT id, at, button FROM presses' 1|2026-08-25 03:11:28|press # so was the GET that fetched the page in the first place $ sqlite3 server 'SELECT count() AS n, path FROM visits GROUP BY path' 1|/ 1|/api/press This web-server is live at https://selfdb.exe.xyz.11If the site is not working for you, sorry. I deployed it on their smallest tier. I included a screenshot of the site just in case for posterity! It is one file, a SQLite database, and it is also the server. It is the website, it is the program, and it is the visitor log and state. §Everything is my demon muse I have a lot of admiration for the work of Justine Tunney, whose prior art redbean: a webserver in a single file, built as an Actually Portable Executable with a self-extracting ZIP archive, inspired the idea. SELF is many ways is less brilliant. It relies on simpler tools to achieve something very similar but I’m amazed how much collapses into a single domain: SQL. Whereas, redbean needs to include an archive format (ZIP), the database itself is the container. Redbean provides Lua hooks to manipulate the responses, whereas the equivalent in SELF is a new row in a handlers table. INSERT INTO handlers VALUES ('/api/busiest', 'SELECT path, count() FROM visits GROUP BY path ORDER BY 2 DESC LIMIT 5'); If redbean is an Actually Portable Executable, this is an Actually Queryable Executable. One of them runs anywhere, the other one you can SELECT from. §All you need is argv[0] How does the process get access to itself? 🤔 For now, you cannot use /proc/self/exe.22Funny enough, the VFS Linux maintainer recently landed support for transparent binfmt_misc in the kernel, which would make /proc/self/exe point to the original file. I wrote about it here. When binfmt_misc matches, the kernel does not execve your file at all , it execs the interpreter, and hands it the path: self-exec passes argv + 1 through to the program, so the program’s argv[0] is the path to the executable itself. The interpreter also releases its SQLite connection before jumping to the entry point, so the program can open its own file and query it. int main(int argc, char argv) { sqlite3 db; / the file the kernel just executed / sqlite3_open(argv[0], &db); ... } This is pretty unrestricted and magical. You can read your own segment table or a new table next to it. The writes persist across invocations. ✨ §self-httpd The web-server for our example is three tables: routes, visits and presses. We will record every visitor and every button press. -- the content, added to the executable -- after it is compiled and linked CREATE TABLE routes (path TEXT PRIMARY KEY, mime TEXT, body BLOB); -- what the site collects, written back -- into the executable while it runs CREATE TABLE visits (id INTEGER PRIMARY KEY, at TEXT, ua TEXT, path TEXT); CREATE TABLE presses (id INTEGER PRIMARY KEY, at TEXT, button TEXT); Building the application feels very unremarkable and familiar. We execute DDL to create the application schema and INSERT the website. # an ordinary ELF for now $ cc -O2 server.c -o server.elf $(pkg-config --libs sqlite3) # the same program, as rows $ elf2self server.elf server $ sqlite3 server < site/schema.sql $ sqlite3 server "INSERT INTO routes VALUES ('/index.html', 'text/html', readfile('site/index.html'))" The asset pipeline looks like a “normal webserver” until you realize it’s querying itself with SQL for the content. Oh, and “itself” is a SQLite database. The page at https://selfdb.exe.xyz shows a lot of fun additional information besides the visitor log and button presses. I included segments, symbols and relocations. Those are not baked in at built time, they are queried from itself while running. §Editing a live site is a transaction Once you have the capability to do ACID transactions, interesting things become possible. The webserver can edit its own content while it is running, and the edits are transactional. The UPDATE is committed to the same file as the program, and a ROLLBACK undoes it. # change the running site. no restart, no reload, no deploy $ sqlite3 server "UPDATE routes SET body = readfile('new.html') WHERE path = '/index.html'" $ curl -s localhost:8080