An artist.getInfo body is a few kilobytes and may be byte-identical for months,
yet the same artist may legitimately be requested two hundred times. Storing a
full body per request would waste roughly an order of magnitude in space, and it
is the same body every time.
Split raw storage in two:
lastfm_response is content-addressed: the primary key is the SHA-256 of the
canonical JSON body (sorted keys, compact separators). An identical body is
stored once; repeats bump last_seen_at and observation_count.lastfm_request logs one row per HTTP attempt, referencing response_id when
a body was received. It is partitioned monthly by requested_at and truncated
it is never: history is the point.Canonicalisation happens before hashing, so key order, whitespace and irrelevant request params cannot create spurious duplicates.
first_seen_at/last_seen_at plus the request
timeline reconstruct it.lastfm_request.response_id uses
ON DELETE RESTRICT, so a response cannot be pruned while observations refer
to it.