<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>lexffe.xyz</title>
    <subtitle>my little tech corner of the internet</subtitle>
    <link rel="self" type="application/atom+xml" href="https://lexffe.xyz/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://lexffe.xyz"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-04-01T00:00:00+00:00</updated>
    <id>https://lexffe.xyz/atom.xml</id>
    <entry xml:lang="en">
        <title>Going through my Spotify history</title>
        <published>2026-04-01T00:00:00+00:00</published>
        <updated>2026-04-01T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://lexffe.xyz/tech-blog/spotify-history/"/>
        <id>https://lexffe.xyz/tech-blog/spotify-history/</id>
        
        <content type="html" xml:base="https://lexffe.xyz/tech-blog/spotify-history/">&lt;h1 id=&quot;premise&quot;&gt;Premise&lt;&#x2F;h1&gt;
&lt;p&gt;I am a giant music nerd and recently I am going through a reminiscing nostalgic trip. I want to know what I used to listen. I found out that Spotify allows you to request a copy of your extended streaming history.&lt;&#x2F;p&gt;
&lt;p&gt;(It is impossible to know my listening history before Spotify. 8 year old me relied on family for music and 12 year old me used to play music on YouTube and Google Music (RIP). I requested a copy of my YouTube data using takeout but none of them are useful (they only preserve 1 year of history it seems.))&lt;&#x2F;p&gt;
&lt;h1 id=&quot;the-data&quot;&gt;The data&lt;&#x2F;h1&gt;
&lt;p&gt;The data came in a zip file. Inside is a README PDF that contains descriptions of the columns.
The actual dataset spans through multiple JSON files, each around 12.8MB big.&lt;&#x2F;p&gt;
&lt;p&gt;An example of a data point may look like this:&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#C6D0F5, #CDD6F4); background-color: light-dark(#303446, #1E1E2E);&quot;&gt;&lt;code data-lang=&quot;javascript&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;[&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;  {&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;ts&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;2020-04-11T00:27:53Z&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;platform&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;iOS 13.4 (iPhone11,8)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;ms_played&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#EF9F76, #FAB387);&quot;&gt; 174674&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;conn_country&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;SG&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;ip_addr&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;203.0.113.x&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;master_metadata_track_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;Jack To The Future (feat. Russoul)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;master_metadata_album_artist_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;Alex Metric&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;master_metadata_album_album_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;Jack To The Future (feat. Russoul)&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;spotify_track_uri&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;spotify:track:74cksX4vgcm0cHKaV7XE2L&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;episode_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;episode_show_name&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;spotify_episode_uri&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;audiobook_title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;audiobook_uri&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;audiobook_chapter_uri&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;audiobook_chapter_title&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;reason_start&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;trackdone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;reason_end&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;trackdone&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;shuffle&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#EF9F76, #FAB387);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;skipped&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#EF9F76, #FAB387);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;offline&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#EF9F76, #FAB387);&quot;&gt; false&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;offline_timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; null&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;    &amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;incognito_mode&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;quot;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#81C8BE, #94E2D5);&quot;&gt;:&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#EF9F76, #FAB387);&quot;&gt; false&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;  }&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);&quot;&gt;,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);font-style: italic;&quot;&gt;  &#x2F;&#x2F;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#949CBB, #9399B2);font-style: italic;&quot;&gt; ...&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;]&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;A few interesting things:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The IP address can be IPv4 and IPv6. A potential normalisation might be using IPv6&#x27;s IPv4-Mapped address prefix like &lt;code&gt;::ffff:1.2.3.4&lt;&#x2F;code&gt;. The database may already have types to deal with IP addresses though.&lt;&#x2F;li&gt;
&lt;li&gt;The IP address may get anonymised at the Spotify side. The last 8-bit of the subnet is replaced with a &lt;code&gt;x&lt;&#x2F;code&gt;.
&lt;ul&gt;
&lt;li&gt;You can still tell which ISP you were on by using &lt;code&gt;bgp.he.net&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;&#x2F;li&gt;
&lt;li&gt;Spotify is being smart and gave us the album artist&#x27;s name. Makes sense because there could be a featuring artist on the track, or it could be a compilation album.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h1 id=&quot;quack&quot;&gt;&quot;Quack&quot;&lt;&#x2F;h1&gt;
&lt;p&gt;Even though it is being given to me in JSON, this looks like tabular data to me. The only reasonable move
is to put it into a database and query it instead of using grep.&lt;&#x2F;p&gt;
&lt;p&gt;For the data size (around 640k rows), I could have also just used SQLite with a CLI but it really isn&#x27;t suitable for analytic workloads, especially if I am enriching the data with more metadata from Spotify later, the joins alone in SQLite would slow down the queries a lot.&lt;&#x2F;p&gt;
&lt;p&gt;At $work we use ClickHouse for large scale data analysis. I am very much used to ClickHouse SQL syntax.
But if this is a personal project, why not use this opportunity to learn a new technology?&lt;&#x2F;p&gt;
&lt;p&gt;I turned to DuckDB as I want a database that&#x27;s as easy to use as SQLite but can handle the data I gave it.&lt;&#x2F;p&gt;
&lt;p&gt;I ingested the data into DuckDB with a tiny bit of normalisation around the IP addresses and I skipped all the
audiobook stuff because I never used it, as well as the podcast stuff.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;file-size&quot;&gt;File size&lt;&#x2F;h2&gt;
&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Format&lt;&#x2F;th&gt;&lt;th&gt;Size (MB)&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;JSON&lt;&#x2F;td&gt;&lt;td&gt;513&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;DuckDB&lt;&#x2F;td&gt;&lt;td&gt;38&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Arrow&lt;&#x2F;td&gt;&lt;td&gt;53.2&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Parquet&lt;&#x2F;td&gt;&lt;td&gt;34.1&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Even with compression, my dataset still weighs 34.1MB. I did some optimisation such as decoding the spotify track URI&#x27;s base62 ID component into blobs and store the blobs, and normalisations like storing tracks in a different table and create a view to join the history table with the track table back together. This took the file size down to 21.8MB. I guess I can further normalise by having the user agent in a different table &#x2F; enum, storing &lt;code&gt;reason_start&lt;&#x2F;code&gt; and &lt;code&gt;reason_end&lt;&#x2F;code&gt; as enums, but that&#x27;s an exercise for later.&lt;&#x2F;p&gt;
&lt;h1 id=&quot;excerpt-on-what-i-found&quot;&gt;Excerpt on what I found&lt;&#x2F;h1&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#C6D0F5, #CDD6F4); background-color: light-dark(#303446, #1E1E2E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;select&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;  distinct&lt;&#x2F;span&gt;&lt;span&gt; artist_name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#8CAAEE, #89B4FA);font-style: italic;&quot;&gt;  count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; count &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; spotify_history_view &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span&gt; ts &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;between&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;2020-01-01&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;2026-04-01&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;GROUP BY&lt;&#x2F;span&gt;&lt;span&gt; artist_name &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; count &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;desc&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;limit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#EF9F76, #FAB387);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;My top 10 artists between 2020 and now are&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;deadmau5,&lt;&#x2F;li&gt;
&lt;li&gt;Flume,&lt;&#x2F;li&gt;
&lt;li&gt;Skrillex,&lt;&#x2F;li&gt;
&lt;li&gt;Bring Me The Horizon,&lt;&#x2F;li&gt;
&lt;li&gt;Lana Del Rey,&lt;&#x2F;li&gt;
&lt;li&gt;London Grammar,&lt;&#x2F;li&gt;
&lt;li&gt;Kendrick Lamar,&lt;&#x2F;li&gt;
&lt;li&gt;Radiohead,&lt;&#x2F;li&gt;
&lt;li&gt;ODESZA, and&lt;&#x2F;li&gt;
&lt;li&gt;The Prodigy.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Not surprising. But when did I actually start listening to them?&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#C6D0F5, #CDD6F4); background-color: light-dark(#303446, #1E1E2E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;with&lt;&#x2F;span&gt;&lt;span&gt; top_artists &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;AS&lt;&#x2F;span&gt;&lt;span&gt; (&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;select&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;  distinct&lt;&#x2F;span&gt;&lt;span&gt; artist_name,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#8CAAEE, #89B4FA);font-style: italic;&quot;&gt;  count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; count,&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;FROM&lt;&#x2F;span&gt;&lt;span&gt; spotify_history_view&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;WHERE&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; timestamp&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; between&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;2020-01-01&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; and&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt; &amp;#39;&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;2026-04-01&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#A6D189, #A6E3A1);&quot;&gt;&amp;#39;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;GROUP BY&lt;&#x2F;span&gt;&lt;span&gt; artist_name&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;ORDER BY&lt;&#x2F;span&gt;&lt;span&gt; count &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;desc&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;limit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#EF9F76, #FAB387);&quot;&gt; 10&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;)   &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;SELECT&lt;&#x2F;span&gt;&lt;span&gt; &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;artist_name, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#8CAAEE, #89B4FA);font-style: italic;&quot;&gt;min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; spotify_history_view &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;JOIN&lt;&#x2F;span&gt;&lt;span&gt; top_artists &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;using&lt;&#x2F;span&gt;&lt;span&gt; (artist_name) &lt;&#x2F;span&gt;&lt;&#x2F;span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;group by&lt;&#x2F;span&gt;&lt;span&gt; artist_name;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;artist_name&lt;&#x2F;th&gt;&lt;th&gt;min(&quot;timestamp&quot;)&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Lana Del Rey&lt;&#x2F;td&gt;&lt;td&gt;2014-03-17 06:44:11&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;The Prodigy&lt;&#x2F;td&gt;&lt;td&gt;2014-12-20 14:24:23&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Bring Me The Horizon&lt;&#x2F;td&gt;&lt;td&gt;2015-02-14 14:45:11&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;London Grammar&lt;&#x2F;td&gt;&lt;td&gt;2014-03-17 20:19:13&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;deadmau5&lt;&#x2F;td&gt;&lt;td&gt;2014-04-14 21:42:46&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Flume&lt;&#x2F;td&gt;&lt;td&gt;2015-01-11 02:35:49&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;ODESZA&lt;&#x2F;td&gt;&lt;td&gt;2014-12-30 01:52:43&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Radiohead&lt;&#x2F;td&gt;&lt;td&gt;2014-05-13 21:03:06&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Kendrick Lamar&lt;&#x2F;td&gt;&lt;td&gt;2015-01-17 23:39:01&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;Skrillex&lt;&#x2F;td&gt;&lt;td&gt;2014-04-12 12:04:00&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;p&gt;Exciting. I have been listening to these artists for more than 10 years.&lt;&#x2F;p&gt;
&lt;p&gt;How about top albums? This is harder to answer with this dataset because there is no play count for each album so we can only estimate based on play counts for each tracks in each album. You can skew this data if you just play one song multiple times. (There might be a way but the SQL is too annoying to conjure.)&lt;&#x2F;p&gt;
&lt;pre class=&quot;giallo&quot; style=&quot;color-scheme: light dark; color: light-dark(#C6D0F5, #CDD6F4); background-color: light-dark(#303446, #1E1E2E);&quot;&gt;&lt;code data-lang=&quot;sql&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;select&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; date&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#8CAAEE, #89B4FA);font-style: italic;&quot;&gt;min&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;timestamp&lt;&#x2F;span&gt;&lt;span&gt;)) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; ts_date, &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#8CAAEE, #89B4FA);font-style: italic;&quot;&gt;count&lt;&#x2F;span&gt;&lt;span&gt;(&lt;&#x2F;span&gt;&lt;span&gt;) &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;as&lt;&#x2F;span&gt;&lt;span&gt; album_count, album_name, artist_name &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;from&lt;&#x2F;span&gt;&lt;span&gt; spotify_history_view &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;group by&lt;&#x2F;span&gt;&lt;span&gt; artist_name, album_name &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;order by&lt;&#x2F;span&gt;&lt;span&gt; album_count &lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt;desc&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#CA9EE6, #CBA6F7);&quot;&gt; limit&lt;&#x2F;span&gt;&lt;span style=&quot;color: light-dark(#EF9F76, #FAB387);&quot;&gt; 20&lt;&#x2F;span&gt;&lt;span&gt;;&lt;&#x2F;span&gt;&lt;&#x2F;span&gt;&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;ts_date&lt;&#x2F;th&gt;&lt;th style=&quot;text-align: right&quot;&gt;album_count&lt;&#x2F;th&gt;&lt;th&gt;album_name&lt;&#x2F;th&gt;&lt;th&gt;artist_name&lt;&#x2F;th&gt;&lt;&#x2F;tr&gt;&lt;&#x2F;thead&gt;&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;2019-03-21&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1225&lt;&#x2F;td&gt;&lt;td&gt;Hi This Is Flume&lt;&#x2F;td&gt;&lt;td&gt;Flume&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2016-12-02&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1167&lt;&#x2F;td&gt;&lt;td&gt;W:&#x2F;2016ALBUM&#x2F;&lt;&#x2F;td&gt;&lt;td&gt;deadmau5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2017-06-04&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;1098&lt;&#x2F;td&gt;&lt;td&gt;hopeless fountain kingdom&lt;&#x2F;td&gt;&lt;td&gt;Halsey&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2014-03-17&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;885&lt;&#x2F;td&gt;&lt;td&gt;If You Wait&lt;&#x2F;td&gt;&lt;td&gt;London Grammar&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2015-09-13&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;885&lt;&#x2F;td&gt;&lt;td&gt;Oh Wonder&lt;&#x2F;td&gt;&lt;td&gt;Oh Wonder&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2014-05-01&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;794&lt;&#x2F;td&gt;&lt;td&gt;No Mythologies to Follow (Deluxe)&lt;&#x2F;td&gt;&lt;td&gt;MØ&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2015-08-03&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;790&lt;&#x2F;td&gt;&lt;td&gt;Down to Earth&lt;&#x2F;td&gt;&lt;td&gt;Flight Facilities&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2015-09-21&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;787&lt;&#x2F;td&gt;&lt;td&gt;BADLANDS&lt;&#x2F;td&gt;&lt;td&gt;Halsey&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2016-05-19&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;772&lt;&#x2F;td&gt;&lt;td&gt;The Life Of Pablo&lt;&#x2F;td&gt;&lt;td&gt;Kanye West&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2017-06-16&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;771&lt;&#x2F;td&gt;&lt;td&gt;Melodrama&lt;&#x2F;td&gt;&lt;td&gt;Lorde&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2015-01-20&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;757&lt;&#x2F;td&gt;&lt;td&gt;My Beautiful Dark Twisted Fantasy&lt;&#x2F;td&gt;&lt;td&gt;Kanye West&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2015-01-30&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;741&lt;&#x2F;td&gt;&lt;td&gt;while(1&amp;lt;2)&lt;&#x2F;td&gt;&lt;td&gt;deadmau5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2014-03-08&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;731&lt;&#x2F;td&gt;&lt;td&gt;True&lt;&#x2F;td&gt;&lt;td&gt;Avicii&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2018-07-13&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;710&lt;&#x2F;td&gt;&lt;td&gt;where&#x27;s the drop?&lt;&#x2F;td&gt;&lt;td&gt;deadmau5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2014-03-17&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;699&lt;&#x2F;td&gt;&lt;td&gt;Settle&lt;&#x2F;td&gt;&lt;td&gt;Disclosure&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2014-03-31&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;686&lt;&#x2F;td&gt;&lt;td&gt;Days Are Gone&lt;&#x2F;td&gt;&lt;td&gt;HAIM&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2019-03-29&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;679&lt;&#x2F;td&gt;&lt;td&gt;WHEN WE ALL FALL ASLEEP, WHERE DO WE GO?&lt;&#x2F;td&gt;&lt;td&gt;Billie Eilish&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2017-06-07&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;677&lt;&#x2F;td&gt;&lt;td&gt;I See You&lt;&#x2F;td&gt;&lt;td&gt;The xx&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2014-04-15&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;670&lt;&#x2F;td&gt;&lt;td&gt;&amp;gt; Album Title Goes Here &amp;lt;&lt;&#x2F;td&gt;&lt;td&gt;deadmau5&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;tr&gt;&lt;td&gt;2016-09-16&lt;&#x2F;td&gt;&lt;td style=&quot;text-align: right&quot;&gt;661&lt;&#x2F;td&gt;&lt;td&gt;New Age | Dark Age (Deluxe Version)&lt;&#x2F;td&gt;&lt;td&gt;Karma Fields&lt;&#x2F;td&gt;&lt;&#x2F;tr&gt;
&lt;&#x2F;tbody&gt;&lt;&#x2F;table&gt;
&lt;h1 id=&quot;after-words&quot;&gt;After words&lt;&#x2F;h1&gt;
&lt;p&gt;This dataset is basically Spotify Wrapped but better.&lt;&#x2F;p&gt;
&lt;p&gt;Spotify recently greatly reduced the amount of data they serve over the Web API.
They no longer serve metadata such as genres, BPM, etc.
My original plan was to write a function (either ClickHouse UDF or some JS) to fetch these metadata on-demand but that&#x27;s no longer viable.&lt;&#x2F;p&gt;
&lt;p&gt;I might jot down the process of getting more metadata out of Spotify, MusicBrainz and Last.fm
in a future post. It is still in progress and involves setting up a MusicBrainz database locally, attempting to pglite and a bit of LLM wrangling. I also want to look into fuzzy text search.&lt;&#x2F;p&gt;
&lt;p&gt;I also have friends asking me how to make this. I might make a little client-side web app for people
to play with. DuckDB has a WASM version so this can all be done without a server.&lt;&#x2F;p&gt;
&lt;p&gt;In the mean time, I&#x27;d like to leave a toy app that generates wallpapers from album arts &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;album-art-wallpaper-gen.vercel.app&#x2F;&quot;&gt;here&lt;&#x2F;a&gt;. (&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;github.com&#x2F;lexffe&#x2F;album-art-wallpaper-gen&quot;&gt;source&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;n-b-i-want-to-share-this-but-nevermind&quot;&gt;N.B. I want to share this but nevermind&lt;&#x2F;h2&gt;
&lt;p&gt;I had a toy site ready to go, that lets people go and query an anonymised version of the data, but
even then LLMs reminded me that AI giants and scrapers could just download the parquet file and
use it for commercial purposes. :&#x2F;&lt;&#x2F;p&gt;
</content>
        
    </entry>
    <entry xml:lang="en">
        <title>Curriculum Vitae</title>
        <published>2026-03-23T00:00:00+00:00</published>
        <updated>2026-03-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://lexffe.xyz/cv/"/>
        <id>https://lexffe.xyz/cv/</id>
        
        <content type="html" xml:base="https://lexffe.xyz/cv/"></content>
        
    </entry>
    <entry xml:lang="en">
        <title>Tech I appreciate from the software engineering world for the past n years.</title>
        <published>2026-03-23T00:00:00+00:00</published>
        <updated>2026-03-23T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Unknown
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://lexffe.xyz/tech-blog/things-i-appreciate/"/>
        <id>https://lexffe.xyz/tech-blog/things-i-appreciate/</id>
        
        <content type="html" xml:base="https://lexffe.xyz/tech-blog/things-i-appreciate/">&lt;p&gt;Over time I see more and more negativity in the software engineering and computer science community. I myself become opinionated and polarised as well. But I realised that this is not good for anyone, especially in the mental health department.&lt;&#x2F;p&gt;
&lt;p&gt;For this post, I want to list out things that bring me joy when using it. It is not just things that I have used before but things I understand and see the potential.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;portable-simd-in-rust&quot;&gt;Portable SIMD in Rust&lt;&#x2F;h2&gt;
&lt;p&gt;I think mechanical sympathy is very underrated. We spend so much time wielding code and sometimes we leave so much performance on the table. My ideal world is that the compiler is smart enough to do autovectorisation. Couple that with instruction level parallelism and out of order execution and your application would be flying. In general, if your code is laid out obvious enough, the compiler does tend to recognise patterns and autovectorise your code. But sometimes your code is just complicated enough, with enough for loops and if branches, that the compiler can’t figure out. Or sometimes you figured out how to calculate all the branches at once.&lt;&#x2F;p&gt;
&lt;p&gt;Recently at $work I have had the privilege and luxury to write high performance code. It is compute heavy and benefits heavily from vectorisation. Unfortunately I made the sin of optimising before measurement. The original code was more or less scalar but I did not check the emitted assembly nor did I do any profiling. So there was no way to tell if autovectorisation ever worked. That said, moving from scalar code to portable SIMD did yield a substantial boost. I did not use external libraries and used &lt;code&gt;std::simd&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Things I appreciate:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;I have never really written SIMD code before so I pair cargo asm with Claude. This creates a nice feedback loop where you can guide optimisation based on the assembly.&lt;&#x2F;li&gt;
&lt;li&gt;The syntax and abstraction works. I look at &lt;code&gt;u32x4&lt;&#x2F;code&gt; and I understand what it means. I don’t need to remember mnemonics.&lt;&#x2F;li&gt;
&lt;li&gt;You can mix and match portable SIMD code with unsafe platform intrinsics. So if you see a codegen behaviour that you don’t think is efficient, then you can use code blocks guarded with platform detection and write with intrinsics.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Things it could improve on:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;The codegen is generally really good, but kind of falls short on ARM targets. AVX codegen works better than NEON, specifically when it comes to swizzling. It is possible that it’s specific to my code. In the end, I prompted Claude to use the portable SIMD code to generate a NEON specific code block.&lt;&#x2F;li&gt;
&lt;li&gt;Portable SIMD is still in nightly...&lt;&#x2F;li&gt;
&lt;li&gt;If I build std during build-time as well (&lt;code&gt;-Zbuild-std&lt;&#x2F;code&gt;), it yields better assembly. I did not spend much time investigating this behaviour.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;(I could have picked C&#x2F;C++ but I have not had good experience writing those before. Dealing with portable SIMD and&#x2F;or intrinsics in C&#x2F;C++ just isn’t on my wishlist. My wish is to write SIMD&#x2F;vectorised code with Zig vectors in some other project.)&lt;&#x2F;p&gt;
&lt;p&gt;References:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;nnethercote.github.io&#x2F;perf-book&#x2F;introduction.html&quot;&gt;https:&#x2F;&#x2F;nnethercote.github.io&#x2F;perf-book&#x2F;introduction.html&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;en.algorithmica.org&quot;&gt;https:&#x2F;&#x2F;en.algorithmica.org&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;h2 id=&quot;zig-cc&quot;&gt;Zig CC&lt;&#x2F;h2&gt;
&lt;p&gt;Zig as a C compiler felt like the same GOARCH+GOOS magic I had. Combining that with cargo zigbuild and we are cross-compiling to every target. The only slight issue I have is that Zig target triples are not the same as the one in Rust.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;jujutsu&quot;&gt;Jujutsu&lt;&#x2F;h2&gt;
&lt;p&gt;My workflow used to be:&lt;&#x2F;p&gt;
&lt;ul&gt;
&lt;li&gt;Checkout new branch&lt;&#x2F;li&gt;
&lt;li&gt;write code&lt;&#x2F;li&gt;
&lt;li&gt;Forgot to commit all the files so I commit all the files into a single commit&lt;&#x2F;li&gt;
&lt;li&gt;Painstakingly refactor the history so the commits make sense&lt;&#x2F;li&gt;
&lt;li&gt;Rebase to main&lt;&#x2F;li&gt;
&lt;li&gt;Colleague reviews my PR&lt;&#x2F;li&gt;
&lt;li&gt;Interactive rebase but pick that one commit that my colleague suggested changes and edits that commit&lt;&#x2F;li&gt;
&lt;li&gt;Stuck in rebase hell and painstakingly resolve all the conflicts&lt;&#x2F;li&gt;
&lt;li&gt;Force push&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;
&lt;p&gt;Now, I am not saying that jujutsu doesn’t have the same steps, but my workflow has been way more pleasant recently. I started off by initialising jujutsu on the main codebase I work on, and I used VisualJJ to move files across changesets. I can put files into their changesets and reordering commits becomes trivial. I was not too happy that I have to open up VSCode just to do jj operations (because right now JJ has lackluster support in IntelliJ), so I moved over to jjui and jj cli. It took me a second to understand changesets (commits) and bookmarks (branches) but it feels so natural now.&lt;&#x2F;p&gt;
&lt;p&gt;I can also prompt Claude Code to create a changeset every time it does something, so I can see the changes individually.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;fast-tooling&quot;&gt;Fast tooling&lt;&#x2F;h2&gt;
&lt;p&gt;People used to write tooling for scripted languages in that specific language. Gulp, babel, webpack were written in JS. Poetry, pipenv, conda were written in Python.&lt;br &#x2F;&gt;
We are definitely seeing a surge of people (re)writing tooling to improve developer experience. UV, TypeScript compiler Go rewrite, esbuild, ripgrep, oxc, are all good examples. Now, I have yet to use any of these tools except uv, but it is really nice to see that there are groups of people dedicating their time to make DX nicer for other devs. UV is now my preferred tool to work with Python.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;gpu-accelerated-ui&quot;&gt;GPU accelerated UI&lt;&#x2F;h2&gt;
&lt;p&gt;I recently moved from VSCode to Zed and it feels really fast. I don’t have any scientific measurements that can back my claim but clicking around and typing feels responsive. It’s the power of Emacs&#x2F;Neovim responsiveness but in a GUI. Ghostty boasts a GPU accelerated terminal as well, just like kitty, alacritty, wezterm, et cetera. I use ghostty mainly for the drop down terminal on macOS but the GPU acceleration is a nice bonus. (https:&#x2F;&#x2F;github.com&#x2F;ghostty-org&#x2F;ghostty#competitive-performance)&lt;&#x2F;p&gt;
&lt;p&gt;It makes so much sense. Why waste the CPU cycles on drawing glyphs in the terminal, when you could offload that to the GPU?&lt;&#x2F;p&gt;
&lt;p&gt;(Although, for heavy coding I am still using the JetBrains suite, which even though it uses way more resources, still manages to be responsive. I guess this is years of optimisation with Java&#x2F;Swing?)&lt;&#x2F;p&gt;
&lt;h2 id=&quot;webassembly&quot;&gt;WebAssembly (?)&lt;&#x2F;h2&gt;
&lt;p&gt;My friend reminded me that we were talking about WebAssembly around 10 years ago (we were 17 at the time…). Unfortunately I do not have the chance to use WASM consciously in my day to day life but this might be the original Java vision. Instead of going and downloading a JRE &#x2F; .NET runtime, you just have a browser, which most consumer electronic devices in the world have.&lt;&#x2F;p&gt;
&lt;p&gt;People are using WASM at the server-side as well! Again, I haven’t had the chance of using it but it seems like a good alternative to container based solutions. You can even run WASM&#x2F;WASI on kubernetes.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;efi-and-efi-stub&quot;&gt;EFI and EFI stub&lt;&#x2F;h2&gt;
&lt;p&gt;I had bad memories when I was messing around dual booting Windows and Linux when I was a kid, messing with the bootloader and disk sectors so BIOS could find the bootloader. Grub rescue is really not something I know how to deal with.&lt;&#x2F;p&gt;
&lt;p&gt;Booting the Linux kernel directly from UEFI feels like magic. There’s no bootloader anymore and there’s one less thing to go through when booting a computer. (When Chrome OS first came out, I kept going back to this video about &lt;a rel=&quot;external&quot; href=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;watch?v=mTFfl7AjNfI&quot;&gt;Chromium OS Fast Boot&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;p&gt;Even though my home server uses Grub nowadays, it’s a nifty knowledge.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;kubernetes-and-infrastructure-as-code&quot;&gt;Kubernetes (and Infrastructure as Code)&lt;&#x2F;h2&gt;
&lt;p&gt;This section might deserve its own post. I used to see k8s as this extra thing you need to run on top of IaaS but now I see the potential. I don’t even think that the control plane reconciliation with your desired state (GitOps or whatever) is the main feature. K8s provided a single API and abstraction for the big clouds. Every cloud has their idiom of doing things on their platform, but k8s is just this one standard and big clouds implement it. I can declare a deployment, a persistent volume and a load balancer and the big cloud translates it to their parlance. Pair that with terraform and you&lt;br &#x2F;&gt;
Of course when you go into minute details this argument tends to break down (IAM is cloud specific, PostgresOperator != managed DB, object storage, etc.), but this taught me that Kubernetes can be a powerful abstraction.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;sqlite&quot;&gt;SQLite&lt;&#x2F;h2&gt;
&lt;p&gt;Nothing much to say other than it is my default flat-file database that just works.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
