af5744f8ab
handleGetHome itself is well-architected (5 sections in parallel via goroutines, latency-bound by the slowest single query). The cold- start lag is two of those queries doing wider scans than necessary. ListLastPlayedArtistsForUser was iterating FROM artists a with a LATERAL play_events join per row — O(total_artists in library) plan even for users who've only played a handful. Inverted: aggregate the user's plays by artist_id first via the play_events → tracks join (uses play_events_user_track_idx + tracks pkey), then attach the artist row and lateral cover/count subqueries only for the artists that actually appear. Cost now bounded by play history, not library size. ListMostPlayedTracksForUser was joining tracks/albums/artists for every play_event row before grouping — O(total plays) work for joins. Pre-aggregated play_events into a CTE keyed by track_id + count(*), then joined to tracks/albums/artists only for the distinct-tracks survivors. Order-by uses the pre-computed count. No handler or generated-Go signature changes — both queries return the same rowset shape, just much faster on libraries where total artists/plays >> distinct-played-artists/distinct-played-tracks.