<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Jaseem Abid</title><description>Jaseem Abid&apos;s blogs and musings</description><link>https://blog.jabid.in/</link><item><title>Big Endian&apos;s Guide to SQLite Storage</title><link>https://blog.jabid.in/2024/11/24/sqlite/</link><guid isPermaLink="true">https://blog.jabid.in/2024/11/24/sqlite/</guid><pubDate>Sun, 24 Nov 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I wanted to learn how databases like SQLite store data under the hood, so I
decided to &lt;a href=&quot;https://github.com/jaseemabid/rsqlite&quot;&gt;write some code&lt;/a&gt; to inspect the database file. SQLite
famously stores the entire database in a &lt;a href=&quot;https://www.sqlite.org/about.html&quot;&gt;single file&lt;/a&gt;, and the
&lt;a href=&quot;https://www.sqlite.org/fileformat2.html&quot;&gt;file format&lt;/a&gt; is very well documented. Here is one diagram&lt;sup&gt;&lt;a href=&quot;#user-content-fn-svg&quot; id=&quot;user-content-fnref-svg&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; to
get started instead of the roughly 13,848 words in that document.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SQLite file format schema diagram&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;880&quot; src=&quot;https://blog.jabid.in/_astro/schema.z9zLW5yC_ZvJ4q6.svg&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;While not impossible, it is somewhat tedious to read through the file format
documentation and figure out what exactly you need to get started. The above
diagram is that minimal starting point.&lt;/p&gt;
&lt;h2 id=&quot;-quick-demo&quot;&gt;🌱 Quick Demo&lt;/h2&gt;
&lt;p&gt;It’s easier to demonstrate this with a quick example. We create a tiny test
database and dump all its internal state with hexdump and a small program I
wrote called &lt;a href=&quot;https://github.com/jaseemabid/rsqlite&quot;&gt;rsqlite&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sql&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;$ sqlite3 &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;planets&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;db&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; &amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; planets&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;sql&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;$ cat &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;planets&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;sql&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;CREATE&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; TABLE&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; planets&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; (&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  id &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; PRIMARY KEY&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;  name&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; TEXT&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;  type&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; TEXT&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  diameter &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  distance &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; NOT NULL&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  moons &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;INTEGER&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; NOT NULL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;INSERT INTO&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; planets (id, &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, diameter, distance, moons) &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;VALUES&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Mercury&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Terrestrial&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;4879&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;57910000&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Venus&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Terrestrial&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;12104&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;108200000&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Earth&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Terrestrial&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;12742&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;149600000&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Mars&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Terrestrial&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;6779&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;227900000&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;5&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Jupiter&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Gas Giant&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;139820&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;778500000&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;79&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;6&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Saturn&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Gas Giant&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;116460&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;1433000000&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;83&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Uranus&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Ice Giant&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;50724&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;2871000000&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;27&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;  (&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Neptune&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt;&apos;Ice Giant&apos;&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;49244&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;4495000000&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates a tiny, mostly empty 8KB file we can play with. Hexdump is smart
enough to avoid duplicate null rows with a single &lt;code&gt;*&lt;/code&gt; and make the output
readable, so we can share the whole contents inline right here. No hidden magic,
this is it!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Side note&lt;/strong&gt;: If you aren’t familiar with hexdump output, the first column is
the offset from the beginning of the file. The 16 columns in the middle are
raw values in hexadecimal and the last section is the ascii representation of
the input data. Anything outside printable range becomes a dot.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ hexdump -C planets.db&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000000  53 51 4c 69 74 65 20 66  6f 72 6d 61 74 20 33 00  |SQLite format 3.|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000010  10 00 01 01 00 40 20 20  00 00 00 02 00 00 00 02  |.....@  ........|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000020  00 00 00 00 00 00 00 00  00 00 00 01 00 00 00 04  |................|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000030  00 00 00 00 00 00 00 00  00 00 00 01 00 00 00 00  |................|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000040  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000050  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 02  |................|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000060  00 2e 7e 58 0d 00 00 00  01 0f 25 00 0f 25 00 00  |..~X......%..%..|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000070  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000f20  00 00 00 00 00 81 58 01  07 17 1b 1b 01 83 07 74  |......X........t|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000f30  61 62 6c 65 70 6c 61 6e  65 74 73 70 6c 61 6e 65  |ableplanetsplane|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000f40  74 73 02 43 52 45 41 54  45 20 54 41 42 4c 45 20  |ts.CREATE TABLE |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000f50  70 6c 61 6e 65 74 73 20  28 0a 20 20 20 20 69 64  |planets (.    id|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000f60  20 49 4e 54 45 47 45 52  20 50 52 49 4d 41 52 59  | INTEGER PRIMARY|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000f70  20 4b 45 59 2c 0a 20 20  20 20 6e 61 6d 65 20 54  | KEY,.    name T|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000f80  45 58 54 20 4e 4f 54 20  4e 55 4c 4c 2c 0a 20 20  |EXT NOT NULL,.  |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000f90  20 20 74 79 70 65 20 54  45 58 54 20 4e 4f 54 20  |  type TEXT NOT |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000fa0  4e 55 4c 4c 2c 0a 20 20  20 20 64 69 61 6d 65 74  |NULL,.    diamet|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000fb0  65 72 20 49 4e 54 45 47  45 52 20 4e 4f 54 20 4e  |er INTEGER NOT N|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000fc0  55 4c 4c 2c 0a 20 20 20  20 64 69 73 74 61 6e 63  |ULL,.    distanc|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000fd0  65 20 49 4e 54 45 47 45  52 20 4e 4f 54 20 4e 55  |e INTEGER NOT NU|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000fe0  4c 4c 2c 0a 20 20 20 20  6d 6f 6f 6e 73 20 49 4e  |LL,.    moons IN|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00000ff0  54 45 47 45 52 20 4e 4f  54 20 4e 55 4c 4c 0a 29  |TEGER NOT NULL.)|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001000  0d 00 00 00 08 0e fc 00  0f df 0f c0 0f a1 0f 82  |................|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001010  0f 61 0f 41 0f 1f 0e fc  00 00 00 00 00 00 00 00  |.a.A............|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001020  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001ef0  00 00 00 00 00 00 00 00  00 00 00 00 21 08 07 00  |............!...|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f00  1b 1f 03 05 01 4e 65 70  74 75 6e 65 49 63 65 20  |.....NeptuneIce |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f10  47 69 61 6e 74 00 c0 5c  00 01 0b ec 41 c0 0e 20  |Giant..\....A.. |&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f20  07 07 00 19 1f 03 05 01  55 72 61 6e 75 73 49 63  |........UranusIc|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f30  65 20 47 69 61 6e 74 00  c6 24 00 00 ab 1f fb c0  |e Giant..$......|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f40  1b 1e 06 07 00 19 1f 03  04 01 53 61 74 75 72 6e  |..........Saturn|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f50  47 61 73 20 47 69 61 6e  74 01 c6 ec 55 69 d8 40  |Gas Giant...Ui.@|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f60  53 1f 05 07 00 1b 1f 03  04 01 4a 75 70 69 74 65  |S.........Jupite|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f70  72 47 61 73 20 47 69 61  6e 74 02 22 2c 2e 66 f7  |rGas Giant.&quot;,.f.|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f80  a0 4f 1d 04 07 00 15 23  02 04 01 4d 61 72 73 54  |.O.....#...MarsT|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001f90  65 72 72 65 73 74 72 69  61 6c 1a 7b 0d 95 7a 60  |errestrial.{..z`|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001fa0  02 1d 03 07 00 17 23 02  04 09 45 61 72 74 68 54  |......#...EarthT|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001fb0  65 72 72 65 73 74 72 69  61 6c 31 c6 08 ea b7 00  |errestrial1.....|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001fc0  1d 02 07 00 17 23 02 04  08 56 65 6e 75 73 54 65  |.....#...VenusTe|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001fd0  72 72 65 73 74 72 69 61  6c 2f 48 06 73 00 40 1f  |rrestrial/H.s.@.|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001fe0  01 07 00 1b 23 02 04 08  4d 65 72 63 75 72 79 54  |....#...MercuryT|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00001ff0  65 72 72 65 73 74 72 69  61 6c 13 0f 03 73 a2 f0  |errestrial...s..|&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;00002000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Some of the internal structure is already visible, but rsqlite makes it a lot
more clear and explicit.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cargo run -q ./data/planets.db .dump&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;SQLite Database Header&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  database page size:  4096&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  write format:        1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  read format:         1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  file change counter: 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  database page count: 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  freelist page count: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  freelist page count: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  schema cookie:       1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  schema format:       4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  default cache size:  0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  autovacuum top root: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  incremental vacuum:  0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  text encoding:       1 (utf8)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  user version:        0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  application id:      0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  software version:    3047000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  number of tables:    ?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  number of indexes:   ?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  number of triggers:  ?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  number of views:     ?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  schema size:         ?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  data version:        ?&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Page 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Page Header:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Type:                    LeafTable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    First freeblock:         0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Number of cells:         1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Cell content start:      3877&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Fragmented free bytes:   0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Cell Pointers:             [3877]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  First 3 Cell Types&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    [String(5), String(7), String(7), I8, String(189)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Cells&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │ Size   │ Row ID │ Col 0  │ Col 1   │ Col 2   │ Col 3 │ Col 4           │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├────────┼────────┼────────┼─────────┼─────────┼───────┼─────────────────┼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │    216 │      1 │ table  │ planets │ planets │ 2     │ CREATE TABLE... │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Page 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Page Header:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Type:                    LeafTable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    First freeblock:         0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Number of cells:         8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Cell content start:      3836&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    Fragmented free bytes:   0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Cell Pointers:             [4063, 4032, 4001, 3970, 3937, 3905, 3871, 3836]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  First 3 Cell Types&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    [Null, String(7), String(11), I16, I32, Zero]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    [Null, String(5), String(11), I16, I32, Zero]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    [Null, String(5), String(11), I16, I32, One]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  Cells&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │ Size │ RowID │ Col 0 │ Col 1   │ Col 2      │ Col 3      │ Col 4      │ Col 5 │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    ├──────┼───────┼───────┼─────────┼────────────┼────────────┼────────────┼───────┼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   31 │     1 │ NULL  │ Mercury │ Terrest... │ 4879       │ 57910000   │ 0     │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   29 │     2 │ NULL  │ Venus   │ Terrest... │ 12104      │ 108200000  │ 0     │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   29 │     3 │ NULL  │ Earth   │ Terrest... │ 12742      │ 149600000  │ 1     │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   29 │     4 │ NULL  │ Mars    │ Terrest... │ 6779       │ 227900000  │ 2     │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   31 │     5 │ NULL  │ Jupiter │ Gas Giant  │ 139820     │ 778500000  │ 79    │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   30 │     6 │ NULL  │ Saturn  │ Gas Giant  │ 116460     │ 1433000000 │ 83    │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   32 │     7 │ NULL  │ Uranus  │ Ice Giant  │ 50724      │ 2871000000 │ 27    │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    │   33 │     8 │ NULL  │ Neptune │ Ice Giant  │ 49244      │ 4495000000 │ 14    │&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;👀 The similarity between the input data, raw hexdump and rsqlite is pretty
clear if you squint&lt;sup&gt;&lt;a href=&quot;#user-content-fn-ui&quot; id=&quot;user-content-fnref-ui&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; hard enough.&lt;/p&gt;
&lt;p&gt;To really understand how the data is stored, we need to take one more step. The
cell pointers at the start of the page point to a set of &lt;a href=&quot;https://www.sqlite.org/fileformat2.html#b_tree_pages&quot;&gt;Leaf Cells&lt;/a&gt;
containing a &lt;a href=&quot;https://www.sqlite.org/fileformat2.html#record_format&quot;&gt;Record&lt;/a&gt; each at the end of the page. Every record
stores the size, types and values of a single database row in a compact block.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;SQLite Cells&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;600&quot; height=&quot;400&quot; src=&quot;https://blog.jabid.in/_astro/cells.BSZuowor_Z25cPvn.svg&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;That’s pretty much all the information you need to get started.&lt;/p&gt;
&lt;h2 id=&quot;-motivating-example-1-database-updates&quot;&gt;🦋 Motivating Example 1: Database Updates&lt;/h2&gt;
&lt;p&gt;It’s really useful to have an exploratory tool of your own to deeply understand
the internals. For example, let’s see how updates are handled.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; sqlite3&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; planets.db&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; &quot;UPDATE planets SET name=&apos;🌍&apos; WHERE id=3;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can make an educated guess from the rather self explanatory diff&lt;sup&gt;&lt;a href=&quot;#user-content-fn-diff&quot; id=&quot;user-content-fnref-diff&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; of the
states.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;diff&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;-- Initial Version&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;++ Inline Update&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;font-weight:bold&quot;&gt;@@ -2,7 +2,7 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   database page size:  4096&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   write format:        1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   read format:         1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;  file change counter: 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;  file change counter: 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   database page count: 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   freelist page count: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   schema cookie:       1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;font-weight:bold&quot;&gt;@@ -45,13 +45,13 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     First freeblock:         0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     Number of cells:         8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     Cell content start:      3836&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    Fragmented free bytes:   0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    Fragmented free bytes:   1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   Cell Pointers:             [4063, 4032, 4001, 3970, 3937, 3905, 3871, 3836]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   First 3 Cell Types&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     [Null, String(7), String(11), I16, I32, Zero]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     [Null, String(5), String(11), I16, I32, Zero]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    [Null, String(5), String(11), I16, I32, One]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    [Null, String(4), String(11), I16, I32, One]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   Cells&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;font-weight:bold&quot;&gt;@@ -59,7 +59,7 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     ├─────┼─────┼───────┼─────────┼────────────┼────────┼────────────┼────┼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │  31 │   1 │ NULL  │ Mercury │ Terrest... │ 4879   │ 57910000   │ 0  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │  29 │   2 │ NULL  │ Venus   │ Terrest... │ 12104  │ 108200000  │ 0  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    │  29 │   3 │ NULL  │ Earth   │ Terrest... │ 12742  │ 149600000  │ 1  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    │  28 │   3 │ NULL  │ 🌍      │ Terrest... │ 12742  │ 149600000  │ 1  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │  29 │   4 │ NULL  │ Mars    │ Terrest... │ 6779   │ 227900000  │ 2  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │  31 │   5 │ NULL  │ Jupiter │ Gas Giant  │ 139820 │ 778500000  │ 79 │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │  30 │   6 │ NULL  │ Saturn  │ Gas Giant  │ 116460 │ 1433000000 │ 83 │&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s a different story when the data cannot be updated in place. The new string
here is longer than the preallocated space, so sqlite does something more
interesting.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;sh&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;$&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; sqlite3&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; planets.db&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; &quot;UPDATE planets SET name=&apos;The pale blue dot&apos; WHERE id=3;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;diff&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;-- Inline Update&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;++ Full Update&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;font-weight:bold&quot;&gt;@@ -2,7 +2,7 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   database page size:  4096&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   write format:        1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   read format:         1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;  file change counter: 3&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;  file change counter: 4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   database page count: 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   freelist page count: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   schema cookie:       1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;font-weight:bold&quot;&gt;@@ -42,16 +42,16 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt; Page 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   Page Header:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     Type:                    LeafTable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    First freeblock:         0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    First freeblock:         4001&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     Number of cells:         8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    Cell content start:      3836&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    Cell content start:      3793&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     Fragmented free bytes:   1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;  Cell Pointers:             [4063, 4032, 4001, 3970, 3937, 3905, 3871, 3836]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;  Cell Pointers:             [4063, 4032, 3793, 3970, 3937, 3905, 3871, 3836]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   First 3 Cell Types&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     [Null, String(7), String(11), I16, I32, Zero]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     [Null, String(5), String(11), I16, I32, Zero]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    [Null, String(4), String(11), I16, I32, One]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    [Null, String(17), String(11), I16, I32, One]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   Cells&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;font-weight:bold&quot;&gt;@@ -59,7 +59,7 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     ├────┼───┼───────┼────────────┼────────────┼────────┼────────────┼────┼&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │ 31 │ 1 │ NULL  │ Mercury    │ Terrest... │ 4879   │ 57910000   │ 0  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │ 29 │ 2 │ NULL  │ Venus      │ Terrest... │ 12104  │ 108200000  │ 0  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    │ 28 │ 3 │ NULL  │ 🌍         │ Terrest... │ 12742  │ 149600000  │ 1  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    │ 41 │ 3 │ NULL  │ The pal... │ Terrest... │ 12742  │ 149600000  │ 1  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │ 29 │ 4 │ NULL  │ Mars       │ Terrest... │ 6779   │ 227900000  │ 2  │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │ 31 │ 5 │ NULL  │ Jupiter    │ Gas Giant  │ 139820 │ 778500000  │ 79 │&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     │ 30 │ 6 │ NULL  │ Saturn     │ Gas Giant  │ 116460 │ 1433000000 │ 83 │&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The whole row is written to a new location (at offset &lt;code&gt;3973&lt;/code&gt;) and the pointers
are updated. Now why is the new pointer offset smaller than the previous one?&lt;/p&gt;
&lt;p&gt;Docs got you covered.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Cell content is stored in the cell content region of the b-tree page. SQLite
strives to place cells as far toward the end of the b-tree page as it can, in
order to leave space for future growth of the cell pointer array.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;By inserting cell pointers at the start of the page from left to right and data
at the end of the page right to left, SQLite is aiming to not waste any disk
space pre allocating any blocks or sections and keep the database as small as
possible. The first cell pointer entry &lt;code&gt;4063&lt;/code&gt; with the largest offset is the
earliest record, written to the end of the page. The rest of the cell pointers
are monotonically decreasing &lt;code&gt;[4032, 4001, ...]&lt;/code&gt; as expected until an update
breaks the order and the cells have to be rearranged.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;first_freeblock&lt;/code&gt; is presumably tracked for the next insertion small enough
to fit there.&lt;/p&gt;
&lt;p&gt;💡 This is the category of things I would have never learned if I didn’t write
this from scratch or paid enough attention.&lt;/p&gt;
&lt;h2 id=&quot;--example-2-vacuum&quot;&gt;💨 🧹 Example 2: Vacuum&lt;/h2&gt;
&lt;p&gt;What really is &lt;a href=&quot;https://www.sqlite.org/lang_vacuum.html&quot;&gt;vacuum&lt;/a&gt;?&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The VACUUM command rebuilds the database file, repacking it into a minimal
amount of disk space.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Let’s just run it and see what happens.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ sqlite3 planets.db &quot;VACUUM;&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And we have this diff again.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;diff&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;-- Full Update&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;++ Vacuum&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;font-weight:bold&quot;&gt;@@ -2,10 +2,10 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   database page size:  4096&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   write format:        1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   read format:         1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;  file change counter: 4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;  file change counter: 5&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   database page count: 2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   freelist page count: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;  schema cookie:       1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;  schema cookie:       2&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   schema format:       4&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   default cache size:  0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   autovacuum top root: 0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#6F42C1;font-weight:bold&quot;&gt;@@ -42,11 +42,11 @@&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt; Page 1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   Page Header:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     Type:                    LeafTable&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    First freeblock:         4001&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    First freeblock:         0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     Number of cells:         8&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    Cell content start:      3793&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;    Fragmented free bytes:   1&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#B31D28&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;-&lt;/span&gt;  Cell Pointers:             [4063, 4032, 3793, 3970, 3937, 3905, 3871, 3836]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    Cell content start:      3824&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;    Fragmented free bytes:   0&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#22863A&quot;&gt;&lt;span style=&quot;user-select: none;&quot;&gt;+&lt;/span&gt;  Cell Pointers:             [4063, 4032, 3989, 3958, 3925, 3893, 3859, 3824]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;   First 3 Cell Types&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#24292E&quot;&gt;     [Null, String(7), String(11), I16, I32, Zero]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We can make the following observations.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;File change counter went up by 1 as expected. Schema cookie also changed, but I have no idea why.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;free_block&lt;/code&gt; is gone, SQLite successfully reclaimed the space in the middle 🧼.&lt;/li&gt;
&lt;li&gt;The rows are ordered once again! I can imagine how running vacuum occasionally can reduce fragmentation and improve
query performance, especially if you don’t have any indexes.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;cell_content_start&lt;/code&gt; used to be 3836 in the first version, moved left to
3793 after second update due to fragmentation and now back right to 3824. All
tidy.&lt;/li&gt;
&lt;li&gt;Compared to the first version, the cell pointers of rows 3-8 changed, only
1,2 remained where it used to be. This is hinting that on large tables with a
lot of changes, vacuum could be potentially very expensive.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;-miscellaneous-lessons-learned&quot;&gt;🧑🏼‍🎓 Miscellaneous lessons learned&lt;/h2&gt;
&lt;p&gt;Other miscellaneous things I learned this week while working on this.&lt;/p&gt;
&lt;h3 id=&quot;-rust-is-very-good-at-this-kind-of-programs&quot;&gt;🦀 Rust is very good at this kind of programs&lt;/h3&gt;
&lt;p&gt;The code to parse the core data structures at &lt;a href=&quot;https://github.com/jaseemabid/rsqlite/blob/main/src/schema.rs&quot;&gt;schema.rs&lt;/a&gt; is only about ~130 LOC
excluding docs, tests and the pretty printer. It took me a moment to
understand&lt;sup&gt;&lt;a href=&quot;#user-content-fn-macro&quot; id=&quot;user-content-fnref-macro&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; the amazing &lt;a href=&quot;https://binrw.rs&quot;&gt;binrw&lt;/a&gt; library I used to read/write the binary
data, but it was remarkably simpler than I expected. Would definitely recommend.&lt;/p&gt;
&lt;h3 id=&quot;️-sqlite-loves-variable-length-encoded-numbers&quot;&gt;⚖️ SQLite loves variable length encoded numbers&lt;/h3&gt;
&lt;p&gt;A substantial fraction of &lt;a href=&quot;https://github.com/jaseemabid/rsqlite/blob/main/src/schema.rs&quot;&gt;schema.rs&lt;/a&gt; is dedicated to SQLite’s variable length
encoded numbers called varints.&lt;/p&gt;
&lt;p&gt;From the docs,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A variable-length integer or “varint” is a static Huffman encoding of 64-bit
twos-complement integers that uses less space for small positive values. A
varint is between 1 and 9 bytes in length. The varint consists of either zero or
more bytes which have the high-order bit set followed by a single byte with the
high-order bit clear, or nine bytes, whichever is shorter. The lower seven bits
of each of the first eight bytes and all 8 bits of the ninth byte are used to
reconstruct the 64-bit twos-complement integer. Varints are big-endian: bits
taken from the earlier byte of the varint are more significant than bits taken
from the later bytes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;SQLite source includes a standalone &lt;a href=&quot;https://github.com/sqlite/sqlite/blob/master/tool/varint.c&quot;&gt;tool/varint.c&lt;/a&gt; which can be compiled into
a small executable to convert numbers varint ↔ decimals. Alternatively see
&lt;a href=&quot;https://github.com/jaseemabid/rsqlite/blob/main/src/varint.rs&quot;&gt;varint.rs&lt;/a&gt; for a naive readable implementation in Rust.&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ cc tool/varint.c -o varint&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;$ ./varint 1992&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;1992 = 8f 48&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Numbers 1-128 would be represented in a single byte, but 128 for example would
need 2 bytes [0x81, 0x00] and 1992 would be [0x8f, 0x48].&lt;/p&gt;
&lt;p&gt;I would naively assume that varints are substantially slower than fixed size
numbers but SQLite must have good reasons to make this tradeoff. Maybe real
world datasets contain a disproportionate amount of small numbers and the size
reduction must be worth the additional complexity. There might even be a perf
gain due to reduced disk IO. Please let me know if you have more background
context on this.&lt;/p&gt;
&lt;h3 id=&quot;-the-native-data-types-are-a-very-small-set&quot;&gt;🎪 The native data types are a very small set&lt;/h3&gt;
&lt;p&gt;Every datatype understood by SQLite at a storage later is documented at &lt;a href=&quot;https://www.sqlite.org/fileformat2.html#record_format&quot;&gt;§
Record Format&lt;/a&gt; and it’s a pretty small set. Notably there is a
dedicated type for numbers 0 and 1 and none for booleans or native timestamps.
SQLite &lt;a href=&quot;https://sqlite.org/datatype3.html&quot;&gt;is not well typed by design&lt;/a&gt; and that is easily my least favorite
part of the whole project.&lt;/p&gt;
&lt;h2 id=&quot;-questions-i-want-to-ask-later&quot;&gt;🚀 Questions I want to ask later&lt;/h2&gt;
&lt;p&gt;I found it really useful to have this project as a starting point to ask more
deeper questions I’ve always had about databases. Recently for an unrelated work
I was looking deeper into DuckDB and how row storage differs from columnar
storage, but you get a much better understanding by dipping your toes into the
code a bit beyond only reading docs. It’s also a &lt;a href=&quot;https://sawyer.dev/posts/rss-reader-progress&quot;&gt;vehicle for
experimentation&lt;/a&gt; for me to learn about databases in general, which I’m
really looking forward to.&lt;/p&gt;
&lt;p&gt;A few questions I’d like to figure out:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;I have only explored the tip of the iceberg here implementing 1 of the 9
different page types. The current version would fail for most non trivial tables
spanning multiple pages for example.&lt;/li&gt;
&lt;li&gt;Figure out how indexes work. How do they maintain the sorted order?&lt;/li&gt;
&lt;li&gt;Are there any tricks to handle really wide rows with 100s of columns?&lt;/li&gt;
&lt;li&gt;Parsing the file for metadata is a non trivial amount of work even with all
the information available in the headers. How much of this state is maintained
internally and reused between queries?&lt;/li&gt;
&lt;li&gt;Types are stored inside each and every record and that feels incredibly
wasteful for properly well typed databases or newer &lt;a href=&quot;https://sqlite.org/stricttables.html&quot;&gt;STRICT tables&lt;/a&gt;.
Figure out if there are ways to make this more efficient.&lt;/li&gt;
&lt;li&gt;Transactions, Journals, Atomic Commits, MVCC, Vacuum, WAL.&lt;/li&gt;
&lt;li&gt;Explore projects in the wider ecosystem like &lt;a href=&quot;https://fly.io/docs/litefs&quot;&gt;litefs&lt;/a&gt; or &lt;a href=&quot;https://github.com/tursodatabase/libsql&quot;&gt;libsql&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;-other-useful-references&quot;&gt;🔗 Other useful references&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://fly.io/blog/sqlite-internals-btree/&quot;&gt;SQLite Internals: Pages &amp;amp; B-trees&lt;/a&gt; by fly.io has a pretty good intro on
varints and record structure. The blog briefly covers the various types of btree
pages in the “Growing a tree” section, but my favorite is when Ben asks “OK, But
Why?” &lt;sup&gt;&lt;a href=&quot;#user-content-fn-why&quot; id=&quot;user-content-fnref-why&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; and follows up with some simple answers.&lt;/li&gt;
&lt;li&gt;Julia Evans’s &lt;a href=&quot;https://jvns.ca/blog/2014/09/27/how-does-sqlite-work-part-1-pages&quot;&gt;How does SQLite work?&lt;/a&gt; takes a very different approach to
the exploratory problem and the blog is nicely complimentary.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://blog.sylver.dev/build-your-own-sqlite-part-1-listing-tables&quot;&gt;Build your own SQLite&lt;/a&gt; by Geoffrey Copin covers a whole lot more than I
did, but our implementations differs a lot.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://cstack.github.io/db_tutorial&quot;&gt;Let’s Build a Simple Database&lt;/a&gt; has some useful info, but the project
is now unmaintained. &lt;del&gt;The spiritual successor is &lt;a href=&quot;https://app.codecrafters.io/courses/sqlite&quot;&gt;CodeCrafter’s Build your own
SQLite&lt;/a&gt; project, but I personally won’t recommend it. The progression b/w
subsequent steps are non linear and it’s not easy to follow through.&lt;/del&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://torymur.github.io/sqlite-repr&quot;&gt;SQLite File Format&lt;/a&gt; might help if you
are starting from scratch again.&lt;/li&gt;
&lt;li&gt;Definitely SQLite source. See the &lt;a href=&quot;https://github.com/sqlite/sqlite/blob/e69b4d7/src/btreeInt.h#L45-L82&quot;&gt;DB Header description&lt;/a&gt; here for
a really good example.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That’s it. FIN 👋🏼&lt;/p&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-svg&quot;&gt;
&lt;p&gt;It took me more time to generate these diagrams than write the entire
code. I used an LLM to generate the basic SVG outline and edited the rest by
hand. I found popular GUI SVG editors incomprehensible and I really couldn’t
make it do the basic things I wanted. &lt;a href=&quot;#user-content-fnref-svg&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-ui&quot;&gt;
&lt;p&gt;I’d love to build a UI tool that can show the bidirectional link between
the raw hexdump and parsed data structures like Godbolt shows the relationship
b/w the high level programming language and the generated assembly. &lt;a href=&quot;#user-content-fnref-ui&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-diff&quot;&gt;
&lt;p&gt;&lt;code&gt;$ diff -u -d --label &apos;Initial Version&apos; state_init.txt --label &apos;Inline Update&apos; state_inline_update.txt&lt;/code&gt; &lt;a href=&quot;#user-content-fnref-diff&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-macro&quot;&gt;
&lt;p&gt;The library makes very heavy use of proc_macros, which I still don’t
understand very well. It’s me, not them. &lt;a href=&quot;#user-content-fnref-macro&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 4&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-why&quot;&gt;
&lt;p&gt;An earlier version of this blog did had the same section but I replaced
it with with 2 motivating examples. Sometimes knowing little details can make a
big difference. I could have massively reduced the size of some time series
datasets I worked with previously if I stored small integers (as low as 1 byte)
instead of floats with decimal points (always 8 bytes). Lookup Gorilla paper for
more info. &lt;a href=&quot;#user-content-fnref-why&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 5&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>Copy URLs from Safari or Chrome with a keyboard shortcut</title><link>https://blog.jabid.in/2024/09/25/safari/</link><guid isPermaLink="true">https://blog.jabid.in/2024/09/25/safari/</guid><pubDate>Wed, 25 Sep 2024 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I really love the &lt;a href=&quot;https://arc.net&quot;&gt;Arc Browser&lt;/a&gt;, but after last week’s &lt;a href=&quot;https://arc.net/blog/CVE-2024-45489-incident-response&quot;&gt;major
security incident&lt;/a&gt;, I wanted to look at some alternatives. They did a
hundred little things to make it the most polished web browser I have
ever used and I will definitely miss it.&lt;/p&gt;
&lt;p&gt;Anyway, I went back to Safari and its many paper cuts. I got used to most of the
quirks, but I would end up pressing ⌘ ⇧ C a dozen times daily to copy the URL,
only to be presented with a very silly element selection feature in dev tools,
which I never need.&lt;/p&gt;
&lt;p&gt;I figured it would be easier to fix the browser than retrain my muscle memory,
and thankfully, there are enough knobs built into macOS to make this not so
painful.&lt;/p&gt;
&lt;h2 id=&quot;step-1-write-some-apple-script&quot;&gt;Step 1: Write some Apple Script.&lt;/h2&gt;
&lt;p&gt;I found the rough template on &lt;a href=&quot;https://www.reddit.com/r/shortcuts/comments/17qqwdv/how_to_create_a_custom_shortcut_in_safari_to_copy/&quot;&gt;reddit&lt;/a&gt;, which I didn’t have to tweak much except
disabling the conflicting keybinding.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a new service in Automation.app&lt;/li&gt;
&lt;li&gt;Select Safari.app, with “workflow receives” set to “no input”.&lt;/li&gt;
&lt;li&gt;Use the following AppleScript&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref aria-describedby=&quot;footnote-label&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; code, and save it with a name like “Copy
Safari URL”.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;applescript&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; run&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; {input, parameters}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;    tell&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; application&lt;/span&gt;&lt;span style=&quot;color:#032F62&quot;&gt; &quot;Safari&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;        set&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; theURL &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; URL&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; of&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; front&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; document&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;        set&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; the&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; clipboard &lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt; theURL&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;    end tell&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;end&lt;/span&gt;&lt;span style=&quot;color:#005CC5&quot;&gt; run&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img alt=&quot;AppleScript Screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2398&quot; height=&quot;1718&quot; src=&quot;https://blog.jabid.in/_astro/applescript.CP2AewOn_ZGRem8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;step-2-enable-the-keybinding-in-keyboard-settings&quot;&gt;Step 2: Enable the keybinding in keyboard settings.&lt;/h2&gt;
&lt;p&gt;Settings &amp;gt; Keyboard &amp;gt; Keyboard Shortcuts &amp;gt; Services &amp;gt; General&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Enable keybinding&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1654&quot; height=&quot;1486&quot; src=&quot;https://blog.jabid.in/_astro/enable.a3s2YY7X_2lvo9r.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2 id=&quot;step-3-disable-the-conflicting-command&quot;&gt;Step 3: Disable the conflicting command&lt;/h2&gt;
&lt;p&gt;Found the basic idea of disabling inbuilt shortcuts from this
&lt;a href=&quot;https://apple.stackexchange.com/questions/392597/in-macos-catalina-10-15-on-safari-how-do-you-disable-command-i-from-composing-a&quot;&gt;StackOverflow&lt;/a&gt; post. You find the exact name of the command you want to
disable (‘Start Element Selection’), and rebind it to something completely
different.&lt;/p&gt;
&lt;p&gt;Settings &amp;gt; Keyboard &amp;gt; Keyboard Shortcuts &amp;gt; App Shortcuts &amp;gt; Safari&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Disable conflicting keybinding&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1654&quot; height=&quot;1486&quot; src=&quot;https://blog.jabid.in/_astro/disable.Cp-CTM0z_Z1Njn4t.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;🎉 📋 Happy Copy Pasting&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;update-1-ditched-safari-went-back-to-chrome&quot;&gt;Update 1: Ditched Safari, went back to Chrome&lt;/h2&gt;
&lt;p&gt;Safari’s paper cuts add up, and it’s time to give Chrome another try.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Safari does not respect “Always open tabs instead of windows” consistently,
it’s infuriating.&lt;/li&gt;
&lt;li&gt;Safari’s vertical tabs implementation is still an alpha product.&lt;/li&gt;
&lt;li&gt;Tab groups are also a good idea, but the implementation is still pretty
rough.&lt;/li&gt;
&lt;li&gt;The tab sync across devices (iPad &amp;amp; iPhone) is pretty neat though! Will miss
it.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;update-2-ditched-chrome-went-back-to-arc-again&quot;&gt;Update 2: Ditched Chrome, went back to Arc again&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;My daily driver is a LG 27“ 5K monitor and no website really needs more than
~1200px. That’s about half of the available horizontal width. Vertical tabs are
so essential for me on desktop, and Arc has the best implementation that I know
of.&lt;/li&gt;
&lt;li&gt;I tried to update the shortcut on Chrome as well, but couldn’t disable the
conflicting inbuilt command. The shortcut is documented &lt;a href=&quot;https://developer.chrome.com/docs/devtools/shortcuts&quot;&gt;here&lt;/a&gt;, but
the exact command string isn’t.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;End of the day, Arc is easily the most polished desktop browser experience on
macOS. They seem to be trying to resolve the incident from last week &lt;a href=&quot;https://arc.net/blog/investing-in-security&quot;&gt;as best
as they can&lt;/a&gt;, so I’m willing to give them another chance.&lt;/p&gt;
&lt;p&gt;🌈 Back to Arc again! Here is my 🎟️ &lt;a href=&quot;https://arc.net/gift/f8bfd621&quot;&gt;invite
code&lt;/a&gt; if you want to give it a try.&lt;/p&gt;
&lt;section data-footnotes class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;AppleScript must be the most bizarre and quirky programming language
ever invented. I can write code in over a dozen programming languages but
AppleScript is the most incomprehensible of them all. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt;
</content:encoded></item><item><title>This blog doesn&apos;t track you anymore!</title><link>https://blog.jabid.in/2020/02/29/track/</link><guid isPermaLink="true">https://blog.jabid.in/2020/02/29/track/</guid><pubDate>Sat, 29 Feb 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I avoid 3rd party tracking on the web as much as I can with several ad blockers
but then forcing it on the readers of this blog felt very hypocritical.&lt;/p&gt;
&lt;p&gt;So I’ve removed all Google Analytics from this blog as of now!&lt;/p&gt;
&lt;p&gt;Fonts, CSS and some icons are loaded from 3rd party CDNs, which I hope to inline
soon. There is a link to Recurse Center below and it contains a unique token for
this blog, but it should not track you.&lt;/p&gt;
&lt;p&gt;Enjoy your privacy and slightly faster loading times 🏎&lt;/p&gt;
</content:encoded></item><item><title>What I talk about when I talk about Programming</title><link>https://blog.jabid.in/2019/10/25/why/</link><guid isPermaLink="true">https://blog.jabid.in/2019/10/25/why/</guid><pubDate>Fri, 25 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Broadly speaking there are programmers who think of programming as a means to an
end and as an end in itself. The instrumental and intrinsic value appeal very
differently to different people.&lt;/p&gt;
&lt;p&gt;I’m usually far more excited about how the TCP packets go from one end to the
other rather than what’s in them. Cat pictures, banking ledgers or irrelevant
spam - they are all the same to me at an abstraction below.&lt;/p&gt;
&lt;p&gt;I must have spent 10000 hours tinkering with programming languages and compilers
in my free time. I’m reasonably proficient at working with static types (like
Rust), functional programming (like Erlang) and the beautiful intersection
between them (like Haskell) even though in the last 5 years, I’ve barely used
any of it at work.&lt;/p&gt;
&lt;p&gt;When I look back at all the side projects I’ve built over the years, none of
them had any implicit value except the fun I had learning about seemingly
pointless and obscure things. I happen to know a lot about arcane x86 calling
conventions now even though I’ll probably never need them in my career. A few
summers ago I was micro optimizing LLVM IR trying to save single-digit bytes of
memory while I’m probably going to be spinning up r4.8xlarge machines on AWS for
the rest of my career. Sometimes I genuinely wish I didn’t know about any of
this so I’d be less opinionated and hence less frustrated about broken software.&lt;/p&gt;
&lt;p&gt;It’s difficult to find your space in a world where 99.99% of programming is
product engineering where you pick whatever tools necessary to get the job done
and mechanical sympathy is seen as an undesirable trait.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Title inspired by 📚 &lt;a href=&quot;https://www.goodreads.com/book/show/2195464.What_I_Talk_About_When_I_Talk_About_Running&quot;&gt;What I Talk About When I Talk About Running&lt;/a&gt;&lt;/p&gt;
</content:encoded></item><item><title>My favorite rust function</title><link>https://blog.jabid.in/2019/10/11/drop/</link><guid isPermaLink="true">https://blog.jabid.in/2019/10/11/drop/</guid><pubDate>Fri, 11 Oct 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;My favorite rust function is &lt;a href=&quot;https://doc.rust-lang.org/std/mem/fn.drop.html&quot;&gt;std::mem::drop&lt;/a&gt; which is used to free or
deallocate a value, similar to &lt;code&gt;free()&lt;/code&gt; in C.&lt;/p&gt;
&lt;p&gt;Quoting the docs from stdlib, This function is not magic; it is literally
defined as&lt;/p&gt;
&lt;pre class=&quot;astro-code github-light&quot; style=&quot;background-color:#fff;color:#24292e; overflow-x: auto;&quot; tabindex=&quot;0&quot; data-language=&quot;rust&quot;&gt;&lt;code&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt; fn&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; drop&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt;T&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;&amp;gt;(_x&lt;/span&gt;&lt;span style=&quot;color:#D73A49&quot;&gt;:&lt;/span&gt;&lt;span style=&quot;color:#6F42C1&quot;&gt; T&lt;/span&gt;&lt;span style=&quot;color:#24292E&quot;&gt;) { }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How could a function definition with an empty body ever be useful?&lt;/p&gt;
&lt;p&gt;Ownership and lifetimes are Rust’s most unique features and it gives you the
predictability and performance of static memory management without any of its
safety problems.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://doc.rust-lang.org/1.30.0/book/2018-edition/ch04-01-what-is-ownership.html#ownership-rules&quot;&gt;ownership rules&lt;/a&gt; are pretty simple.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Each value in Rust has a variable that’s called its owner.&lt;/li&gt;
&lt;li&gt;There can only be one owner at a time.&lt;/li&gt;
&lt;li&gt;When the owner goes out of scope, the value will be dropped.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Calling a function moves the ownership of the arguments and if the called
function decides to do nothing with it, the arguments will be dropped - which is
exactly what we wanted!&lt;/p&gt;
&lt;p&gt;Now this might seem like a hack, but it really is not. Most languages would
either ask the programmers to explicitly call &lt;code&gt;free()&lt;/code&gt; or implicitly call a
magic &lt;code&gt;runtime.deallocate()&lt;/code&gt; within a complex garbage collector.&lt;/p&gt;
&lt;p&gt;The beauty of programming language design is not building the most complex
edifice like Scala or making the language unacceptably restricted like Go - but
giving the programmer the ability to represent complex ideas elegantly and
safely. Rust really shines in that regard.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A language that doesn’t affect the way you think about programming is not
worth knowing.
― Alan J. Perlis&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;This post was edited after publishing, see the full &lt;a href=&quot;https://github.com/jaseemabid/blog/commits/master/_posts/2019-10-11-drop.md&quot;&gt;history&lt;/a&gt; on github.&lt;/p&gt;
</content:encoded></item><item><title>An Incremental Approach to Compiler Construction 🎤</title><link>https://blog.jabid.in/2019/09/17/pwl/</link><guid isPermaLink="true">https://blog.jabid.in/2019/09/17/pwl/</guid><pubDate>Tue, 17 Sep 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I spoke at &lt;a href=&quot;https://www.meetup.com/Papers-We-Love-London/events/264717689&quot;&gt;Papers We Love, London&lt;/a&gt; about my &lt;a href=&quot;https://github.com/jaseemabid/inc&quot;&gt;toy compiler&lt;/a&gt; and the
video is up on YouTube!&lt;/p&gt;
&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/WBWRkUuyuE0&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture&quot; allowfullscreen&gt;&lt;/iframe&gt;
</content:encoded></item><item><title>Wealth of Nations</title><link>https://blog.jabid.in/2019/05/29/wealth/</link><guid isPermaLink="true">https://blog.jabid.in/2019/05/29/wealth/</guid><pubDate>Wed, 29 May 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I grew up and spent the first 25 years of my life in India. I lived a short
while in NYC to attend the &lt;a href=&quot;https://blog.jabid.in/2017/08/10/rc&quot;&gt;recurse center&lt;/a&gt; and now I live in the UK. I saw
a bit more of the tiny blue marble in the meanwhile.&lt;/p&gt;
&lt;p&gt;Hans Rosling says in &lt;a href=&quot;https://www.goodreads.com/book/show/34890015-factfulness&quot;&gt;Factfulness&lt;/a&gt; that you cannot divide the world into broad
“First” and “Third” world categories anymore and the divide is closing; but as
someone who got to see a fair bit of both sides of the spectrum, it is my
opinion that the divide is unspeakably huge and is much worse than he paints it
to be. I earn almost 2x per day today than my first monthly salary out of
college doing pretty much the same job. Life can change a lot when you get paid
70x.&lt;/p&gt;
&lt;p&gt;India is unspeakably poor. &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_countries_by_GDP_(PPP)_per_capita&quot;&gt;Purchasing power&lt;/a&gt; is around 120th among the 180
countries tracked by the world bank. &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_countries_by_literacy_rate&quot;&gt;Literacy rate&lt;/a&gt; is around the
same bracket. What the average British could take for granted a 100 years ago
won’t happen in India for another century. Looking at the current state of the
nation, it is only getting much worse.&lt;/p&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;Not a day go by without me thinking over and over again how fundamentally different the rich first world and the rest of it is. Yes I&amp;#39;ve read Factfullness and I think he missed a party of elephants in the room. The more I see, read and learn the more depressing it gets.&lt;/p&gt;&amp;mdash; Jaseem Abid (@jaseemabid) &lt;a href=&quot;https://twitter.com/jaseemabid/status/1130037075712061440?ref_src=twsrc%5Etfw&quot;&gt;May 19, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;br/&gt;
&lt;p&gt;I’ve been thinking &lt;em&gt;a lot&lt;/em&gt; about what makes some countries wealthy and some
poor. I enjoy learning macro economics and I hope to spend time in the next few
months learning more; hopefully updating this post with details.&lt;/p&gt;
&lt;br/&gt;
&lt;blockquote class=&quot;twitter-tweet&quot; data-lang=&quot;en&quot;&gt;&lt;p lang=&quot;en&quot; dir=&quot;ltr&quot;&gt;What&amp;#39;s the modern equivalent of Adam Smith&amp;#39;s Wealth of Nations? I normally enjoy reading &lt;a href=&quot;https://twitter.com/hashtag/economics?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#economics&lt;/a&gt; and I&amp;#39;d love to read more about how nations build their economies and the factors that make them wealthy or poor. I&amp;#39;d like to get over my own biases. &lt;a href=&quot;https://twitter.com/hashtag/book?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#book&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/suggestions?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#suggestions&lt;/a&gt; &lt;a href=&quot;https://twitter.com/hashtag/goodreads?src=hash&amp;amp;ref_src=twsrc%5Etfw&quot;&gt;#goodreads&lt;/a&gt;&lt;/p&gt;&amp;mdash; Jaseem Abid (@jaseemabid) &lt;a href=&quot;https://twitter.com/jaseemabid/status/1132562549793316864?ref_src=twsrc%5Etfw&quot;&gt;May 26, 2019&lt;/a&gt;&lt;/blockquote&gt;
&lt;br/&gt;
&lt;hr&gt;
&lt;p&gt;Here are some of the book suggestions from the twitter thread.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;1. The Wealth of Nations by Adam Smith&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I’m honestly not sure if much of this is relevant anymore since he spends maybe
30% of the book talking about wheat prices in London. Its over 1200 pages long
and a bit too dry to keep reading.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://www.econlib.org/library/Smith/smWN.html&quot;&gt;Econ lib summary&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.investopedia.com/updates/adam-smith-wealth-of-nations/&quot;&gt;Investopedia summary&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;2. Why Nations Fail: The Origins of Power, Prosperity, and Poverty&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;I’ve a paperback already, so this might be the first in the list.&lt;/p&gt;
&lt;p&gt;&lt;i class=&quot;fab fa-youtube&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=jsZDlBU36n0&quot;&gt;Why nations fail | James Robinson | TEDxAcademy&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;3 Debt: The First 5,000 Years by David Graeber&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;i class=&quot;fab fa-youtube&quot;&gt;&lt;/i&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=CZIINXhGDcs&quot;&gt;DEBT: The First 5,000 Years | David Graeber | Talks at Google&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;4. Poor Economics: A Radical Rethinking of the Way to Fight Global Poverty&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;5. Development as Freedom by Amartya Sen&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;6. The Rise and Fall of Nations: Forces of Change in the Post-Crisis World by Ruchir Sharma&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;7. The wealth of Networks by Yochai Benkler&lt;/em&gt; &lt;a href=&quot;https://www.benkler.org/Benkler_Wealth_Of_Networks.pdf&quot;&gt;(pdf)&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Let me know your thoughts. You can reach me over
&lt;a href=&quot;mailto:jaseemabid@gmail.com&quot;&gt;email&lt;/a&gt; or &lt;del&gt;&lt;i class=&quot;fab fa-twitter&quot;&gt;&lt;/i&gt;
&lt;a href=&quot;https://twitter.com/jaseemabid&quot;&gt;@jaseemabid&lt;/a&gt;&lt;/del&gt;&lt;/p&gt;
</content:encoded></item><item><title>Amsterdam, A history of the world&apos;s most liberal city 📚</title><link>https://blog.jabid.in/2019/05/10/amsterdam/</link><guid isPermaLink="true">https://blog.jabid.in/2019/05/10/amsterdam/</guid><pubDate>Fri, 10 May 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I finished reading “&lt;a href=&quot;https://www.goodreads.com/book/show/17288660-amsterdam&quot;&gt;Amsterdam, A history of the world’s most liberal
city&lt;/a&gt;” last week and absolutely loved it. 5/5 🌟&lt;/p&gt;
&lt;p&gt;The book is equally about a place, the people and an ideology it stands for -
liberalism. &lt;em&gt;Gedogen&lt;/em&gt; in Dutch means &lt;em&gt;“illegal but tolerated”&lt;/em&gt; and Amsterdam
seems to have developed this curious and unique attitude to so many social
issues. There aren’t so many places in the world where human rights are equally
respected, where you can smoke weed legally, sit by the canals appreciating
architectural marvels, bike around almost anywhere without being run over by
cars and appreciate some Rembrandt and Van Gogh in the most majestic art
museums. The vibe is just magical and unreal. If you are curious about why
things are the way they are, it’s impossible to leave the city without getting a
few history books and that’s exactly what I did at the &lt;a href=&quot;https://abc.nl&quot;&gt;American Book
Store&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Jordaan&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;4032&quot; height=&quot;3024&quot; src=&quot;https://blog.jabid.in/_astro/jordaan.i9sFnz8M_1rNYqz.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The narration is beautiful. This is definitely a history book - the author
describes how they built a city by draining the sea and building a dam to
prevent the floods and how the &lt;a href=&quot;https://en.wikipedia.org/wiki/Dutch_East_India_Company&quot;&gt;Dutch East India Company&lt;/a&gt; made them
immensely rich with trade and colonialism. We also meet real people who start
over their lives leaving behind everything and moving to unknown lands to become
early settlers. We read about true pioneers like &lt;a href=&quot;https://en.wikipedia.org/wiki/Aletta_Jacobs&quot;&gt;Aletta Jacobs&lt;/a&gt; who made
remarkable progress fighting for women’s rights and suffrage and &lt;a href=&quot;https://nl.wikipedia.org/wiki/Benno_Premsela&quot;&gt;Benno
Premsela&lt;/a&gt; for gay rights. We meet celebrities like Anne Frank, Rembrandt and
Spinoza. History books can’t just describe a sequence of events - this one is an
avalanche of emotions, people and stories you cannot forget.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Jordaan&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3024&quot; height=&quot;4032&quot; src=&quot;https://blog.jabid.in/_astro/steps.uIoCAREd_1jL5wi.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/New_Amsterdam&quot;&gt;New&lt;/a&gt; and Old Amsterdams are 2 of my favourite cities in the world and this book
made me realize again how connected they really are. Manhattan’s grid layout
impressed me more than every other human achievement combined - sending humans
to Mars looks so simple in comparison. This could be because I spent the 5 years
before moving to NYC in one of the world’s most congested cities were going from
one end to the other was an unspeakable nightmare. Every single day I commuted
the length of the island from 125 St to Canal St without it being a ceremony,
I’ve asked myself how NYC could do in &lt;a href=&quot;https://en.wikipedia.org/wiki/Commissioners%27_Plan_of_1811&quot;&gt;1811&lt;/a&gt; what India cannot do now 200 years
later. How could some parts of the world be &lt;em&gt;centuries&lt;/em&gt; ahead of others?&lt;/p&gt;
&lt;p&gt;The book describes an incident in which the English had to find a Dutch
translator more than 100 years after the Dutch left to negotiate a trade deal
with the native Indian population because it was the only European language
known to them. Somehow Manhattan’s grid is so obvious after Amsterdam’s canals.
It might not seem like the most astonishing human achievement to you, but I had
such a great moment of epiphany connecting the dots.&lt;/p&gt;
&lt;p&gt;NYC and Amsterdam both evolved to becoming the most liberal and cosmopolitan
cities in the world. Both were at some point world’s wealthiest cities, largest
ports and after opening doors to flocks of immigrants during days of prosecution
and crisis, the most diverse as well.&lt;/p&gt;
&lt;p&gt;To understand the extent of the VOC trade empire at the height of the Dutch
Golden age, we could look at this would map from 1630.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/Nova_totius_Terrarum_Orbis_geographica_ac_hydrographica_tabula_%28Hendrik_Hondius%29_balanced.jpg/1920px-Nova_totius_Terrarum_Orbis_geographica_ac_hydrographica_tabula_%28Hendrik_Hondius%29_balanced.jpg&quot;&gt;&lt;img src=&quot;https://upload.wikimedia.org/wikipedia/commons/thumb/b/b5/Nova_totius_Terrarum_Orbis_geographica_ac_hydrographica_tabula_%28Hendrik_Hondius%29_balanced.jpg/1920px-Nova_totius_Terrarum_Orbis_geographica_ac_hydrographica_tabula_%28Hendrik_Hondius%29_balanced.jpg&quot; alt=&quot;map&quot;&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Just 100 years after the first European reached India via the sea, we have a map
that looks remarkably similar to the precise GPS versions we have now. This is
before most of the science as we know of was invented. The company that
dominated world trade also lead to one of the &lt;a href=&quot;https://en.wikipedia.org/wiki/Euronext_Amsterdam&quot;&gt;first stock exchanges&lt;/a&gt; where
the average citizen invested some of their savings to lay the foundation of
modern capitalism.&lt;/p&gt;
&lt;p&gt;To be honest, even though I just said all that, during the short time I spent
there I could barely find any brown people in the cafes and pubs I spent hours
reading. The Dutch were liberal, but they definitely made life in Indonesia and
other colonies hell and they waged wars all over the world including &lt;a href=&quot;https://en.wikipedia.org/wiki/Travancore%E2%80%93Dutch_War&quot;&gt;one quite
close to where I was born and brought up&lt;/a&gt;. More Jews died proportionately
in Amsterdam than almost anywhere else in Europe during WW2. There was
definitely a time when the Catholic priests and nuns were stripped and killed
and churches desecrated. A prime minister was killed on the streets and
decapitated. &lt;a href=&quot;https://en.wikipedia.org/wiki/Refugees_of_the_Syrian_Civil_War&quot;&gt;Dutch Immigration laws aren’t great&lt;/a&gt; compared to Germany. I
took me 46 days to get a 45 day &lt;a href=&quot;https://twitter.com/jaseemabid/status/1113789086928707584&quot;&gt;Schengen&lt;/a&gt; visa.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Jordaan&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;3024&quot; height=&quot;4032&quot; src=&quot;https://blog.jabid.in/_astro/library.MwUyC8WL_Z18TJN8.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;There is a whole lot more. A brief glimpse into the Dutch monarchy and we learn
how closely tied every European monarchy really is. The dutch &lt;a href=&quot;https://en.wikipedia.org/wiki/William_III_of_England#Invasion_of_England&quot;&gt;took over&lt;/a&gt;
the English crown once without even a war. For a while 30% of all the books
published in world were from Amsterdam. Roots of religious tolerance and how
Protestantism replaced Roman Catholicism. There is a lot said about how NYC
influenced the rest of America and what it stands for. Obviously a lot about the
canals and the tulip mania. This book made me think hard and I loved it ❤️&lt;/p&gt;
</content:encoded></item><item><title>Loneliness</title><link>https://blog.jabid.in/2019/05/04/1/</link><guid isPermaLink="true">https://blog.jabid.in/2019/05/04/1/</guid><pubDate>Sat, 04 May 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The difficult part about moving halfway across the world is the loneliness that
comes with it. No matter what you do and who you meet, often it’s just
impossible to replace those loved ones.&lt;/p&gt;
</content:encoded></item><item><title>Small lessons I learned at Monzo 🚀</title><link>https://blog.jabid.in/2019/01/13/monzo/</link><guid isPermaLink="true">https://blog.jabid.in/2019/01/13/monzo/</guid><pubDate>Sun, 13 Jan 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I’m a Platform Engineer at &lt;a href=&quot;https://monzo.com&quot;&gt;Monzo&lt;/a&gt; since August 2018 and a recent
conversation made me think of all the things I’ve learned over the last 4 short
months. I wanted to share about how we work and what I’ve learned here.&lt;/p&gt;
&lt;p&gt;Briefly, the Monzo banking platform is roughly 820 micro services on Kubernetes.
Some of them run a handful of replicas while others run into over 100. As of
writing, we run over 6200 pods in about 350 nodes. Except for a small set of
physical servers required to connect to various payment networks, everything
else runs on AWS. Almost all data is stored in Cassandra with a little bit of
Elastic Search. Kafka and NSQ act as message brokers. Prometheus and Grafana
offer extensive monitoring. See the blog &lt;a href=&quot;https://monzo.com/blog/2016/09/19/building-a-modern-bank-backend/&quot;&gt;Building a Modern Bank
Backend&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;The platform team is split into 2 squads, one that concentrates on the
infrastructure and reliability while the other takes care of engineering
effectiveness. I’m part of the former and that in practice means we provision,
scale and monitor the infrastructure required to run the bank and continuously
make improvements to support a rapidly evolving product and the roughly 100
engineers working on it.&lt;/p&gt;
&lt;p&gt;Monzo is the largest &lt;del&gt;company&lt;/del&gt; project I’ve ever worked on in terms of users,
engineers, lines of code and scale. A ton of the software we use was new to me
and I had lots of fun (and a fair share of anxiety) learning them all as quickly
as possible during the first 2 or 3 months. I’ve learned a lot about how some
specific software works like Kubernetes, Cassandra and Wireguard but the soft
skills or life lessons were far more valuable. When I look back, the relief that
not all software engineering jobs in the world suck makes me so much happier 🙏.&lt;/p&gt;
&lt;h2 id=&quot;1-culture-can-make-an-enormous-difference-&quot;&gt;1. Culture can make an enormous difference 🏦&lt;/h2&gt;
&lt;p&gt;We have a &lt;a href=&quot;https://monzo.com/blog/2018/03/22/diversity-and-inclusion&quot;&gt;diverse workforce&lt;/a&gt; building something together that they
(and their moms) would love to use and would be proud of. I worked on developer tools
at a previous job and every single engineer on the project I knew of
passionately hated the project and never used any of it. It is impossible to be
a productive engineer and look ahead while you are soaked in so much toxicity. I
see employees excited about what we can already do and the mountain of
possibilities ahead of us. Conversations change from bitching about management
to knowledge sharing and cool feature updates over lunch. You go back to your
desk happy. It is a very powerful feedback cycle.&lt;/p&gt;
&lt;p&gt;We acquired a &lt;a href=&quot;https://monzo.com/blog/2018/09/24/one-million-monzo-customers/&quot;&gt;million customers in just about 3 years&lt;/a&gt; while
maintaining a &lt;a href=&quot;https://twitter.com/t_blom/status/1006817371816955904&quot;&gt;NPS score over +80&lt;/a&gt;. We had an incredible &lt;a href=&quot;https://monzo.com/blog/2018/12/05/crowdfunding-closes/&quot;&gt;crowdfunding&lt;/a&gt;
round raising 20M£ in just under 3hrs which shows how much customers believe in
the product. I think behind every milestone, there are a lot of happy employees
loving what they do. This manifests as proactively &lt;a href=&quot;https://monzo.com/blog/2018/09/07/ba-data-breach&quot;&gt;sending customers new cards
even before they realise that British Airways leaked their information&lt;/a&gt; or
the &lt;a href=&quot;https://monzo.com/blog/2018/12/17/customer-support&quot;&gt;whole company joining hands to answer support queries&lt;/a&gt; when the
wait times got high.&lt;/p&gt;
&lt;h2 id=&quot;2-scaling-teams-and-code-&quot;&gt;2. Scaling teams and code 👩‍💻&lt;/h2&gt;
&lt;p&gt;Almost all of the application code is in Go and each micro service is a top
level folder in a monorepo built with a few shared libraries and tools and works
incredibly well for us. New engineers can start with a service without having to
learn about the whole platform. Experiments and old features and get cleaned up
when it’s not needed anymore because its usually just deleting a service and a
few callers into it. Service deployments are independent of each other and
usually, there are more than 50 deployments every day.&lt;/p&gt;
&lt;p&gt;I learned how valuable good tooling is. A small engineering effectiveness team
can make the lives of so many engineers so much better when the tools to deploy,
monitor, check logs etc “just work”. If you can deploy and rollback safely with
just one single command, it encourages engineers to deploy small and often
making the whole process a lot safer. This improves confidence in doing things
and helps engineers iterate so much faster. I’ve wasted days in the past
building completely unrelated downstream projects after changing shared Jenkins
libraries. Never again.&lt;/p&gt;
&lt;p&gt;💡 Invest in tooling.&lt;/p&gt;
&lt;h2 id=&quot;3-a-good-orientation-matters-&quot;&gt;3. A good orientation matters 🧭&lt;/h2&gt;
&lt;p&gt;Please don’t link your next new engineer to a git repo and README.md and expect
them to find everything on their own. Every company have unique ways of doing
things, the context that is not written down anywhere and broken processes that
everyone is not aware of.&lt;/p&gt;
&lt;p&gt;A “buddy” 👫 for the first week or so just to show you how everything works can
be a huge bonus 💪. I started at Monzo looking into how we run our database
cluster and mistakes there would have been costly. I cannot overstate how much
having someone to ask dumb questions helped. Come back &lt;a href=&quot;https://twitter.com/spikelindsey&quot;&gt;@spikelindsey&lt;/a&gt;!&lt;/p&gt;
&lt;h2 id=&quot;4-scaling-infrastructure-&quot;&gt;4. Scaling infrastructure 💾&lt;/h2&gt;
&lt;p&gt;I’ve never been in a platform/infrastructure/devops role before and I had to
start at level 0. The most complicated thing I had done with AWS before Monzo
was to setup a VM for a tiny web application. It took me quite some time to get
used to the nuances of Terraform to manage a large production fleet. It took a
while to clean up some of the cruft left behind, but we are very close to the
state of the entire infrastructure described in Terraform and Puppet and
&lt;em&gt;“Infrastructure as code”&lt;/em&gt; is taken for granted at Monzo. Being able to raise a
Terraform PR and discuss it instead of clicking random buttons in the EC2 UI 🕵️‍♀️
made it so much easier for a newbie like me to get work done.&lt;/p&gt;
&lt;p&gt;Not rocket science 🚀 but you should switch to a tool that lets you describe
infrastructure as code asap.&lt;/p&gt;
&lt;h2 id=&quot;5-technical-debt-&quot;&gt;5. Technical debt 🕸&lt;/h2&gt;
&lt;p&gt;I learned that at the heart of it, &lt;em&gt;technical debt is a cultural problem than a
technical problem&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;When I started, the puppet code we used for configuring infrastructure at Monzo
was really old and crufty, but now we are actually spending time and effort to
clean it up. I was mad about not version controlling our Grafana dashboards and
not syncing them across prod and staging environments - I fixed it last week.
Some of our critical infrastructure diverged from the version controlled config,
we fixed it too. We needed centralised logging and distributed tracing, both got
shipped in the last 3 months. The operations around Cassandra improved massively
over the last 6 or 7 months. And several other projects that I’m not aware of
are getting fixed right now.&lt;/p&gt;
&lt;!--

I really want to bitch about redhat, but the people reading this won&apos;t learn
anything out of it. Leaving the next paragraph here as a comment instead of
deleting. Fuck you RH, I&apos;ll forever be pissed off at you for ruining a year of
my life and causing so much trauma.

I worked on [fabric8.io][f8]/[openshift.io][osio] at Redhat and it was an
absolute nightmare. I&apos;d wait days building completely unrelated downstream
projects after making trivial changes to shared Jenkins pipelines. The project
was the epitome of bad software engineering and couldn&apos;t get any worse. The code
quality was abysmal and cleaning it up would have required a collaborative team
effort with several people involved. Allocating time for cleaning up and
throwing away cruft would have required convincing multiple team leads and
managers and none of them understood or cared about the problems engineers
faced. The huge _difference in incentives_ made sure nothing ever got done. I
quit after 8 months unable to make even the smallest changes to the project - it
was the worst failure of my career which I&apos;m still unable to get over. I&apos;ve
faced a similar environment in most places I&apos;ve worked or consulted before.

--&gt;
&lt;p&gt;There is cruft and mess in every large software out there but they differ in how
people deal with it. Unless you have a culture of fixing things up once in a
while, eventually it compounds so much to make it hell. Under some conditions,
&lt;a href=&quot;https://monzo.com/blog/2018/06/29/engineering-principles&quot;&gt;technical debt is a useful tool&lt;/a&gt; but you need to be careful about it.
It’s a thin line. The next time I come across something badly broken at Monzo, I
know I can eventually get it fixed and won’t have to live with it forever.
Building that culture is hard, but would pay off massively in the long run.&lt;/p&gt;
&lt;h2 id=&quot;6-monitoring-&quot;&gt;6. Monitoring 📈&lt;/h2&gt;
&lt;p&gt;Good infrastructure starts with good monitoring and alerts. I’ve never worked
with any sort of serious monitoring before and I do not want to go back. I
learned Prometheus and Grafana at Monzo and they are both really good at what
they do and I developed some sort of fascination for pretty informative charts.
Each graph is a story. Here are some random ones I liked:&lt;/p&gt;
&lt;p&gt;We changed the way Kubernetes pods connect to the database and you can see in
the first graph how one policy changes to the other cleanly and in the second
graph how the cluster picks DB nodes more intelligently considering several
factors rather than a simple round robin. This would be impossible to understand
from just logs.&lt;/p&gt;
&lt;p&gt;![](./round to hostpool.png)
&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2530&quot; height=&quot;1162&quot; src=&quot;https://blog.jabid.in/_astro/connections.Dv6r7reN_2jIAid.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This graph on open file descriptors helped us track down a leak in the
&lt;a href=&quot;https://github.com/prometheus/jmx_exporter/issues/327&quot;&gt;Prometheus JMX exporter&lt;/a&gt; and fix it.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;Number of open file descriptors&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;2684&quot; height=&quot;1159&quot; src=&quot;https://blog.jabid.in/_astro/fd.BaXDwraM_Z2h1ViE.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This one shows how Kafka acts as a nice message buffering queue and lets us
restart databases for a short time with no visible downtime.&lt;/p&gt;
&lt;p&gt;&lt;img alt=&quot;&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; width=&quot;1703&quot; height=&quot;601&quot; src=&quot;https://blog.jabid.in/_astro/kafka.DK6dSwzR_ZiAH8t.webp&quot; srcset=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;And a few more.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;We have a strong feedback culture and people do it frequently. It helps you
learn about the problems early and act on it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;I went to an actual data centre and learned a little bit about how the
physical infrastructure works. Fascinating.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Making processes inclusive for remote workers forces us to write down a lot
more documentation which is awesome.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Cassandra is a really really complicated piece of software to understand, use
and operate. I’m having a love hate relationship with it right now. More on
it later.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Go works really well for Monzo but I’m not a fan of it. Almost everyone else
seems to love it. I’m extremely biased when it comes to programming languages
because I spent most of my free time thinking about Haskell.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;p&gt;It a been a long one with lessons, rants and stories. Let me know what you
think. Thanks a lot to &lt;a href=&quot;https://twitter.com/indradhanush92&quot;&gt;@indradhanush92&lt;/a&gt;, &lt;a href=&quot;https://twitter.com/aishpant&quot;&gt;@aishpant&lt;/a&gt;,
&lt;a href=&quot;https://twitter.com/vimalk78&quot;&gt;@vimalk78&lt;/a&gt; and &lt;a href=&quot;https://twitter.com/rusrushal13&quot;&gt;@rusrushal13&lt;/a&gt; for proof reading early
versions of this draft.&lt;/p&gt;
</content:encoded></item></channel></rss>