How it works
The story behind this site. How it's built and what was learned.
Architecture
Every Sunday, cron runs the whole pipeline on one Hetzner box: Python snapshots Last.fm into Postgres, dbt models it, and a JSON export feeds this static site.
Data model
Only raw tables live in Postgres; every transformation is a dbt model. Full lineage and column docs are in the dbt docs.
Lessons learned
Simpler > trendier
Music Growth originally had a Next.js/React frontend. Due to its complexity and my unfamiliarity with the framework, I rewrote the frontend in simple HTML/Tailwind CSS/JS, drawing from a JSON export layer. The frontend shrank from 53 โ 9 files and 9,226 โ 721 lines.
Neon vs. the JSON export layer
This site originally drew from a cloud Postgres server (Neon). However, the data is small enough to live in the same cloud instance that hosts the frontend. A weekly script turns modeled Postgres data into JSON files the frontend can read directly. This is simpler, faster, and more cost-effective.
Compare over equal windows
This page once said bigger artists grow faster. When a second analysis disagreed, I dug in and found why: I had added ~16k artists to the tracked set weeks after the rest, so most small artists were measured over about half as many weeks as large ones. Now every artist is measured over the same weeks, and the result flipped.
What the data says
Growth means new listeners, not more plays
Last.fm counts every user who has ever played an artist as a listener, so the number only goes up. Listener growth here means new people finding an artist, not existing fans playing more.
Smaller artists grow faster
Median listener growth falls steadily from the smallest fifth of artists to the largest.
Last.fm's chart ranks by scrobbles, not size
Last.fm's chart API orders artists roughly by scrobble count, so chart position isn't a measure of size. I group artists into listener-count quintiles before comparing them instead.
Some artist names are redacted by a regex profanity filter. If yours was caught by mistake, let me know.
If you made it to the bottom of this page, thanks for sticking around! You may want to check out my other stuff.