Engineering · May 1, 2026 · 6 min read

The producer flywheel: closing the loop both ways

Three rounds ago the demand-queue arc still had a hole. Searchers had a reason to come back — their searches climbed a public queue, pushed got fired when their artist landed, the catalog bent toward what they asked for. Producers had no equivalent pull. The page existed; they had to remember to check it. This week the producer side got its own loop. Now both sides have ambient reasons to keep showing up.

The asymmetry the original arc shipped with

The five-round Hunting Now arc was end-to-end on the consumer side. Search an artist StudioMode doesn't have, your search lands in missing_artist_requests, the next scrape pulls the top-priority rows first, beats land, and a push notification fires the moment your specific artist gets saved to the catalog. "🎯 EBK Jaaybo just landed." Tap, deep-link into search, hear what you came for. That's a complete pull-side loop. Searchers come back because their asks materialize.

The asymmetry was the push side. Producers are the ones who can actually fulfill demand — but the original arc gave them no surface. /hunting-now existed as a public page; a producer would have to bookmark it and remember to check. That works for fans of a tool. It doesn't work for an ecosystem. We needed an ambient producer-side hook that sat in the producer's existing daily routine, not one more tab to remember to open.

RSS, of all things

The answer was deeply unfashionable: an RSS feed. Subscribe at /hunting-now.rss in any feed reader (Feedly, Inoreader, NetNewsWire, Reeder) and new high-priority demand entries appear inline with whatever else the producer is already reading. The producer doesn't think about StudioMode. StudioMode thinks about them.

One serverless function. Hits the same public_demand_queue RPC the public page already uses. Edge-cached for 30 minutes. Each item is one queue row:

<item>
  <title>EBK Jaaybo · 12 searches</title>
  <link>https://studiomode.app/hunting-now#ebk-jaaybo</link>
  <guid isPermaLink="true">https://studiomode.app/hunting-now#ebk-jaaybo</guid>
  <pubDate>Thu, 30 Apr 2026 14:23:11 GMT</pubDate>
  <category>pending</category>
  <description><![CDATA[12 searches for EBK Jaaybo-type beats. Waiting in queue. StudioMode catalog doesn't have matching beats yet — make some and they'll be the first to land.]]></description>
</item>

The link goes to a hash anchor on /hunting-now so a click from the feed reader scrolls to the actual queue row, not just the page. The category is the row's status — feed readers that group by category surface "pending" and "queued" as separate buckets. The description is copy aimed at the producer reading it, not the searcher.

Why this composes correctly

The flywheel only works when both spokes are spinning. Before this round, the consumer spoke spun fine — searches landed, pushes fired, catalog grew toward demand — but the producer spoke was static. The catalog grew, but only via what the scraper already knew to look for. New artists outside the master list were always reactive: a user had to ask for them first. Every demand fulfillment was a delayed reaction to a search that already happened.

The catalog only bent toward demand reactively. The producer side was never given a way to be proactive — until now, when it became one row in their morning feed.

With RSS, a producer who follows the feed sees an artist's demand row the same day a user submits it. They make a beat that night. The next StudioMode scrape catches their YouTube upload via the marketplace-URL path. The demand row flips to scraped. The original searcher gets a push notification ("🎯 EBK Jaaybo just landed"). The producer's beat shows up at the top of the search the next user runs. One artist, one cycle, three constituencies served, zero coordination.

The full loop, both directions

2
Spokes spinning
1
Serverless function
30m
Edge cache
0
New tables

Drawn out:

  1. User searches an artist StudioMode doesn't have.
  2. Row lands in missing_artist_requests at priority 1, status pending.
  3. Same row appears on /hunting-now (public RPC, no cache).
  4. Same row appears in /hunting-now.rss within 30 minutes (edge-cache window).
  5. Producer subscribed to the feed sees the row in Feedly next morning. Recognizes the sound. Makes a beat. Uploads to YouTube.
  6. Next StudioMode scrape (every 12h) catches the upload via the marketplace-URL path. Row flips to scraped.
  7. Original searcher gets a push: "🎯 EBK Jaaybo just landed." They tap. Deep-link into search. Hear the producer's beat.
  8. Producer's beat now sits in the catalog under "EBK Jaaybo type beats." Future searchers find it without needing to ask. The /hunting-now row drops off (it's scraped; the public RPC only returns pending + queued).

Eight steps. Three different actors (searcher, producer, scraper). Zero direct coordination — every handoff is async, every state transition is a database write. The system is basically a state machine where the actors just observe its transitions through different surfaces.

What we didn't build

The version that didn't ship is also worth naming. We could have built a /producer-portal page with charts, filters, sort orders, "make this beat" CTAs, leaderboards of who fulfilled the most demand this week, points, badges, gamification. Producers had no surface, so giving them a brand-new dedicated one felt like the obvious move.

But every line of UI we ship is a line of UI we have to maintain, get producers to remember, optimize against. RSS pulls the producer in via a tool they already use. We don't have to make the page sticky. The feed reader is sticky.

The other thing we didn't build is push notifications for producers. Every time a new high-priority row lands, ping every producer who's previously fulfilled demand of that genre? Tempting. But producers haven't asked for it, and adding push to a constituency that hasn't asked for it is the kind of "feature" that stops a flywheel rather than spinning it. RSS is opt-in by design. Push is opt-in technically but feels assumed. We're starting where the consent is unambiguous.

The transparency strip

One adjacent thing that fell out of this arc: a scraper-status strip at the top of /hunting-now showing three numbers — last scrape time, queue depth, next-run ETA. The same anon-callable RPC pattern as everything else (public_scraper_status() returning (last_run_minutes_ago, pending_queue_depth, cron_interval_hours) in one round-trip), rendered as a three-cell strip above the queue list.

Why it matters here: it removes the producer's reasonable doubt about whether the queue is real. A producer reading the RSS feed for the first time can land on /hunting-now, see "Last scrape: 3h 12m ago · 47 artists waiting · Next run ~9h", and know the system is alive. Without it, the queue could be static demo data. With it, the heartbeat is visible. Trust-building artifact, not a feature.

Producers — subscribe via RSS

One feed, every queue update. Pick the next sound to make beats in based on actual user demand.

Get the Hunting Now feed →

What's next

Open question: should we surface "fulfilled by you" anywhere to producers who claim their profile? "12 of your beats came from demand-queue requests this month" is the kind of stat that converts a producer from passive feed-subscriber to active partner. Probably the next ~30 lines on the producer profile page plus a new RPC. We'll see if the RSS subscription data shows enough adoption to justify it.

© 2026 StudioMode · Both spokes spinning.