Imported History Is Provenance Not Playback Truth
Imported history is provenance not playback truth
Imported history can be useful without being equivalent to observed behavior.
That sounds obvious until the product wants a single analytics table. Then the temptation is to take an external event, put it beside local events, and let every chart pretend they were measured the same way. That is where the lie creeps in.
The rule
If a record came from outside the system, keep the raw source and mark the measurement kind before it enters analytics.
For music history:
- local playback can know pause time, stop time, progress, private-session state, and sometimes decoded audio samples
- a Last.fm scrobble is mostly a timestamped "this listen qualified somewhere else"
- Spotify's own history can expose recently played tracks, but it does not mean the local app observed the whole listening session
These are all useful. They are not the same fact.
Why the distinction matters
The analytics question changes depending on provenance.
"What tracks did I listen to most?" can include imported scrobbles.
"How many minutes did I actually hear?" should not silently treat imported scrobbles as sample-counted playback.
"Did I skip this track after 12 seconds?" cannot be reconstructed from a scrobble. If the import system guesses, the guess should be named.
The product shape
The cleaner shape is:
- store raw imported rows in an audit table
- dedupe by provider, user, timestamp, and normalized source fields
- resolve to local objects only when confidence is high
- promote into analytics with an explicit
measurement_kind - keep unresolved rows visible without forcing them into charts
- make undo remove promoted analytics effects, not the raw audit trail
That keeps the import reversible without destroying the evidence.
Where this came from
The Spotuify Last.fm import work exposed the difference between a good plan and current code truth.
The current main branch still has analytics import/export as reserved command surfaces that return a follow-up error. It also has an AudioCounterTap in the embedded audio path, but the daemon SessionTracker still computes listen facts from elapsed time minus paused intervals. The playback_progress table exists and gets pruned, but current code does not insert production progress samples.
So the useful learning is not "Last.fm import shipped." It has not shipped on main. The useful learning is the design constraint: imported history belongs in local analytics only when its provenance travels with it.