Generating 1.4 Billion Personalized Music Narratives for Wrapped Archive

spotify · Media & Entertainment · 2025 · source Agentic: no · promotional bias: low · source-backed · extracted with prompt 0.5.6 (schema v2)

Generated from extraction.json — do not edit by hand. Every claim cites verbatim source evidence; stated means the quote directly asserts the claim, implied means it supports it indirectly.

Problem

Domain: personalized content generation at global launch scale

Spotify needed to generate personalized Wrapped Archive narratives for hundreds of millions of users, grounded in real listening data, while keeping the stories creative, safe, non-repetitive, cost-feasible, concurrency-safe, and ready for a single global launch moment.

Constraints:

Architecture

Spotify built an offline generation system for Wrapped Archive. A distributed data pipeline ranked each user's listening days by narrative potential, stored up to five remarkable days and relevant listening history in object storage, then published work to a pubsub queue. A fine-tuned production model generated one report at a time per user, using previous reports to avoid repetition, while reports were persisted in a column-oriented key-value store designed for concurrent day-level writes. Separate evaluation, logging, remediation, capacity-planning, and launch-warming systems made the billion-report batch safe to generate and serve.

Diagram confidence: explicit (topology described by the source).

flowchart LR
  listening_history_events["Listening history events"] --> remarkable_day_heuristic_pipeline["Remarkable-day heuristic pipeline"]
  remarkable_day_heuristic_pipeline --> object_storage_snapshots["Object storage snapshots"]
  object_storage_snapshots --> pubsub_generation_queue["Pubsub generation queue"]
  prompt_and_prototype_tooling["Prompt and prototype tooling"] --> fine_tuned_production_model["Fine-tuned production model"]
  prompt_and_prototype_tooling --> human_review_loop["Human review loop"]
  pubsub_generation_queue --> fine_tuned_production_model
  fine_tuned_production_model --> report_content_table["Report content table"]
  fine_tuned_production_model --> evaluation_data_warehouse["Evaluation data warehouse"]
  report_content_table --> completion_metadata_columns["Completion metadata columns"]
  report_content_table --> serving_path["Serving path"]
  completion_metadata_columns --> serving_path
  evaluation_data_warehouse --> llm_as_judge_evaluators["LLM-as-judge evaluators"]
  evaluation_data_warehouse --> remediation_loop["Remediation loop"]
  llm_as_judge_evaluators --> remediation_loop
  human_review_loop --> remediation_loop
  remediation_loop --> fine_tuned_production_model
  remediation_loop --> report_content_table
  serving_path --> wrapped_users["Wrapped users"]
Drag to pan · scroll or use +/− to zoom · reconstructed from the source's described component topology

Components

Component Role Interacts with
Listening history events Raw yearly listening behavior used to identify interesting days and ground narrative content. Remarkable-day heuristic pipeline
Remarkable-day heuristic pipeline Priority-ordered heuristics that rank candidate days by narrative potential and statistical strength. Object storage snapshots
Object storage snapshots Per-user remarkable-day data and relevant listening history stored before report generation. Pubsub generation queue
Pubsub generation queue Asynchronous work queue that feeds report-generation jobs to the generation engine. Fine-tuned production model
Prompt and prototype tooling Prompt comparison, edge-case review, and structured logging tools used to iterate creative and safety behavior. Fine-tuned production model, Human review loop
Fine-tuned production model Smaller production model distilled from frontier-model references and DPO-tuned for Wrapped Archive report generation. Report content table, Evaluation data warehouse
Report content table Table keyed by user and date that stores full generated report content before completion metadata is written. Completion metadata columns, Serving path
Completion metadata columns Per-day column qualifiers that mark which remarkable days have completed reports without read-modify-write coordination. Serving path
Evaluation data warehouse Corpus-wide analysis store for generated reports, optimized for ad-hoc QA queries and model-judge evaluation. LLM-as-judge evaluators, Remediation loop
LLM-as-judge evaluators Larger models that grade report samples across accuracy, safety, tone, and formatting dimensions. Remediation loop
Human review loop Brand, design, and safety reviewers who inspect samples, compare prompts, and curate preference data. Prompt and prototype tooling, Remediation loop
Remediation loop Process for tracing failures, fixing upstream bugs or guardrails, deleting affected reports, and replaying generation. Fine-tuned production model, Report content table
Serving path Pre-scaled compute and database serving layer warmed before the global Wrapped launch spike. Wrapped users
Wrapped users Hundreds of millions of listeners who receive personalized Wrapped Archive narratives at launch. Serving path

Data flow

Listening history is first reduced into candidate remarkable days by priority-ordered heuristics. The selected day data and listening context are stored in object storage and published asynchronously to a queue. A fine-tuned model generates report text, with earlier reports available as context for later reports for the same user. Report content is written before lightweight completion metadata in a column-oriented database. Generated reports are copied into an evaluation warehouse, judged by larger models and targeted human review, and problematic cohorts can be deleted, fixed upstream, and replayed before the pre-scaled serving path handles the Wrapped launch spike.

3 supporting quotes
“We used a distributed data pipeline to compute and aggregate candidate days at the user level.”article, stated
“we published these data points onto a messaging queue that allowed the next stage of the system to consume the data points asynchronously.”article, stated
“Writes followed a deliberate order: first the report content, then a lightweight metadata entry marking the day as complete.”article, stated

Why this architecture

Spotify separated candidate-day computation, offline generation, storage, evaluation, remediation, and launch serving because every part had a different scaling risk. Pre-generation avoided launch-time model latency, distillation made a billion model calls economically feasible, column-oriented writes removed coordination from concurrent report completion, and automated evaluation/replay handled quality failures that human review could not inspect at full corpus scale.

3 supporting quotes
“High-performance models were excellent for prototyping, but running them to generate over a billion reports was economically unfeasible.”article, stated
“Concurrent writes for different days therefore touch completely different cells within the same row, hence no coordination, no locks, no read-modify-write cycles.”article, stated
“Reactive scaling simply doesn’t move fast enough.”article, stated

Models used: LLM · frontier model · fine-tuned production model · larger models acting as judges

Scale

Alternatives considered (roads not taken)

Use high-performance frontier models for every production report

Rejected because: The article says frontier models were useful for prototyping but economically infeasible for more than a billion report generations.

“High-performance models were excellent for prototyping, but running them to generate over a billion reports was economically unfeasible.”article, stated

Track completed days as a serialized list in a user row

Rejected because: A read-modify-write list would have risked lost updates when multiple day reports completed concurrently for the same user.

“A naive read-modify-write approach to tracking completed days would have been vulnerable to race conditions and lost updates.”article, stated

Depend on reactive autoscaling during Wrapped launch

Rejected because: Wrapped traffic spikes instantly, so Spotify pre-scaled and warmed infrastructure before real traffic arrived.

“Auto-scaling reacts to observed load. Wrapped doesn’t ramp, it spikes! Reactive scaling simply doesn’t move fast enough.”article, stated

Evaluate every generated report with model judges

Rejected because: To preserve efficiency, Spotify evaluated a large random sample instead of the full 1.4 billion-report corpus.

“To preserve the efficiency gains from distillation, we evaluated a large random sample (~165,000 reports) rather than the full corpus.”article, stated

Use one massive evaluation prompt

Rejected because: Spotify split judging into smaller rule-based queries to reduce non-determinism and allow parallel grading.

“Instead of one massive evaluation prompt, we used multiple smaller rule-based queries per report. This reduced non-deterministic results and allowed parallel grading.”article, stated

Patterns

batch-offline-processing (generation architecture)

Spotify pre-generated all Wrapped Archive reports offline before launch, using object storage, a pubsub queue, and asynchronous processing to run the billion-report workload ahead of user traffic.

“all pre-generated before Wrapped launch day.”article, stated
“we published these data points onto a messaging queue that allowed the next stage of the system to consume the data points asynchronously.”article, stated

model-distillation (model optimization)

Spotify used frontier-model outputs to create a reviewed gold dataset, then fine-tuned a smaller production model and applied DPO to make generation economically feasible.

“We used a frontier model to produce high-quality reference outputs.”article, stated
“We then fine-tuned a smaller, faster production model on this dataset, transferring the quality of the larger model into a more efficient form.”article, stated

eval-driven-development (quality and safety loop)

Prompting, LLM-as-judge evaluations, human review, structured logging, and remediation all fed back into prompt and generation changes.

“Prompting wasn’t a linear process. It was a loop.”article, stated
“Creative, technical, and safety feedback all fed into the next iteration.”article, stated

llm-as-judge (automated evaluation)

Spotify used larger models as judges to grade generated reports across accuracy, safety, tone, and formatting dimensions.

“Evaluation was performed by larger models acting as judges (LLM as a judge).”article, stated
“Each report was graded across four dimensions: accuracy, safety, tone, and formatting.”article, stated

human-in-the-loop-gate (creative and safety review)

Human review shaped prompt iteration, curated the distillation/preference data, and participated in targeted remediation for problematic reports.

“We ran LLM-as-a-judge evaluations on sampled outputs. We layered in human review.”article, stated
“powered by A/B-tested human evaluations. Although the preference dataset was relatively small, it was highly curated and intentionally constructed.”article, stated

guardrails-io-filtering (prompt safety controls)

The system prompt encoded a creative contract that required data-grounded storytelling and excluded unsafe or off-brand content categories.

“Trust and safety by default: avoid references to drugs, alcohol, sex, violence, or offensive language.”article, stated
“Data-driven storytelling: every insight had to be traceable to actual listening behavior.”article, stated

observability-tracing (generation monitoring and fault isolation)

Spotify used real-time dashboards, structured logging, report IDs, and full metadata to monitor generation and trace corpus-level failures back to upstream causes.

“Our real-time dashboards gave us visibility into report generation progress, system reliability, and projected completion time.”article, stated
“Because we were running structured evaluations and logging report IDs with full metadata, we could trace the problem back to the source”article, stated

durable-execution (replay and recovery)

After detecting bad outputs, Spotify could delete affected reports, fix the upstream issue or guardrail, and replay generation safely for those reports.

“Once the initial pass completed, we carefully combed through the output to detect missing reports, data inconsistencies, and any other issues”article, stated
“fix the pipeline, delete the affected reports in bulk, and replay them safely.”article, stated

prompt-versioning (prompt iteration)

Spotify treated prompt design as a daily multi-month practice, comparing prompt versions and edge cases through prototype tooling.

“Prompting became a daily practice for more than three months.”article, stated
“We used a prototype to compare outputs across prompt versions and edge cases.”article, stated

Tradeoffs

Use a distilled production model for bulk generation.

Chose A smaller fine-tuned model trained from reviewed frontier-model references over Running high-performance frontier models for every report.

Rationale: The frontier model was good for prototyping, but the economics of over a billion production calls required a smaller faster model.

“High-performance models were excellent for prototyping, but running them to generate over a billion reports was economically unfeasible.”article, stated
“We then fine-tuned a smaller, faster production model on this dataset”article, stated

Pre-generate reports before launch.

Chose An offline batch generation engine over Generating each narrative on-demand during Wrapped traffic.

Rationale: Launch arrives as a global spike and each report requires a model call, so pre-generation moved model latency and throughput risk out of the user-facing path.

“Each report required a call to our fine-tuned model. That meant sustaining thousands of requests per second for days, under strict latency constraints.”article, stated
“Wrapped launches globally at a single moment. There’s no gradual rollout.”article, stated

Generate one report at a time per user.

Chose Sequential per-user report generation with previous reports as context over Fully independent generation of all reports for a user.

Rationale: Earlier reports informed later reports so the generated stories could avoid repetition across a user's archive.

“generating one report at a time per user, so earlier reports could inform later ones to avoid repetition.”article, stated

Model completion metadata as independent per-day cells.

Chose Column qualifiers by date within a user's row over A serialized completed-days list updated through read-modify-write.

Rationale: Independent cells let concurrent report completions land without locks or coordination, avoiding lost updates.

“Rather than storing a serialized list of completed days, we gave each day its own column qualifier within a dedicated column family”article, stated
“hence no coordination, no locks, no read-modify-write cycles.”article, stated

Sample for model-based evaluation.

Chose A large random sample of about 165,000 reports over LLM-judge evaluation of the entire corpus.

Rationale: Sampling preserved the efficiency gains from distillation while still giving Spotify corpus-level QA signal.

“To preserve the efficiency gains from distillation, we evaluated a large random sample (~165,000 reports) rather than the full corpus.”article, stated

Pre-scale and warm infrastructure before launch.

Chose Pre-scaled compute/database capacity plus synthetic regional load tests over Waiting for autoscaling to react to observed demand.

Rationale: Wrapped traffic spikes too abruptly for reactive scaling, so Spotify warmed compute, caches, database tablets, and provider capacity before real users arrived.

“We pre-scaled compute pods and database node capacity hours before launch.”article, stated
“We ran them long enough to cover the critical launch window. When real traffic arrived, nothing was cold.”article, stated

Gotchas (what bit them)

A tiny failure rate becomes millions of bad experiences at Wrapped scale.

Root cause: The corpus had more than a billion reports, so even 0.1% bad output would affect millions of users.

Resolution: Spotify built automated evaluation, sampled model judging, structured logging, targeted human review, and remediation loops instead of relying on manual review.

“even a 0.1% failure rate would translate to millions of “broken” stories.”article, stated
“Human review at this scale is impossible. So we built an automated evaluation framework.”article, stated

Creative LLM output could hallucinate, stereotype, or drift off-brand.

Root cause: The reports were personalized narratives, so factual grounding, emotional tone, and safety constraints all had to hold simultaneously.

Resolution: Spotify split the prompt into a system-level creative contract and a user prompt that supplied detailed listening logs, stats, prior reports, and country context.

“We needed prompts that could reliably generate creative, emotionally resonant stories, without hallucinating, stereotyping, or drifting off-brand.”article, stated
“The user prompt removed ambiguity. Each generation included:”article, stated

Model math weakness could corrupt personalized narratives.

Root cause: The generation input included raw listening logs, but the model was not trusted to compute listening statistics correctly.

Resolution: Spotify included a summarized stats block in the prompt so the model could narrate rather than calculate.

“A summarized stats block (LLMs are bad at math)”article, stated

Concurrent report writes for the same user risked lost completion state.

Root cause: Each user could have up to five reports generated independently, so multiple writes for the same row could arrive nearly simultaneously.

Resolution: Spotify modeled each remarkable day as its own column qualifier, avoiding locks and read-modify-write updates.

“Each user could have up to five reports, generated independently and written concurrently.”article, stated
“Concurrent writes for different days therefore touch completely different cells within the same row, hence no coordination, no locks, no read-modify-write cycles.”article, stated

Reactive autoscaling would be too slow for a global Wrapped launch.

Root cause: Traffic jumps from idle to millions of users at once, leaving no gradual ramp for autoscaling signals.

Resolution: Spotify pre-scaled compute and database capacity, coordinated model-provider capacity, and ran synthetic regional load tests to warm compute and storage.

“Wrapped doesn’t ramp, it spikes! Reactive scaling simply doesn’t move fast enough.”article, stated
“We pre-scaled compute pods and database node capacity hours before launch.”article, stated

The model faithfully amplified an upstream data bug into confident wrong stories.

Root cause: A subtle timezone bug surfaced the wrong top discovery day, and the model generated a compelling narrative from that incorrect input.

Resolution: Structured evaluations and report metadata let Spotify trace the bug, quantify affected reports, fix the pipeline, bulk-delete, and replay safely.

3 supporting quotes
“a subtle timezone bug in the upstream data pipeline occasionally surfaced the wrong top discovery day.”article, stated
“The model faithfully wrote a compelling story about it.”article, stated
“trace the problem back to the source, quantify its prevalence across the corpus, fix the pipeline, delete the affected reports in bulk, and replay them safely.”article, stated

More prompt instructions could reduce creative quality.

Root cause: Stacking constraints on the generator made output less creative even when instructions were well-intentioned.

Resolution: Spotify treated prompt and evaluation design as a coupled loop and learned to keep prompts lean enough to preserve story quality.

“Less is more! The more instructions we piled on, the less creative the output became.”article, stated
“Prompt and evaluation design have to evolve together.”article, stated

Evaluation

Spotify combined prompt-version comparisons, LLM-as-judge grading, human review, structured logging, corpus queries, regex-based matching, and replay. Larger judge models graded sampled production reports for accuracy, safety, tone, and formatting, while targeted review and metadata tracing drove remediation.

Metrics: accuracy · safety · tone · formatting · preference parity with the original baseline · throughput · system reliability · projected completion time · missing reports · data inconsistencies

3 supporting quotes
“Each report was graded across four dimensions: accuracy, safety, tone, and formatting.”article, stated
“the fine-tuned production model achieved strong preference parity with the original baseline.”article, stated
“Our real-time dashboards gave us visibility into report generation progress, system reliability, and projected completion time.”article, stated

Outcomes

The project operated at unusually high batch and launch scale: roughly 350 million eligible users, up to five reports per user, around 1.4 billion generated reports, thousands of model requests per second for days, and a single global launch moment where elevated latency could affect millions.

3 supporting quotes
“By the end of pre-generation, over a billion reports were stored and ready to be served.”article, stated
“For four days straight, the generation engine ran without pause!”article, stated
“Wrapped Archive reached hundreds of millions of users around the world.”article, stated