DEV Community

Cover image for The payments inversion — building a Lightning revenue-share loop where the app pays the user
ItsEvilDuck
ItsEvilDuck

Posted on

The payments inversion — building a Lightning revenue-share loop where the app pays the user

In the last post I argued that Stripe — and the card network underneath it — can’t serve certain payment shapes, no matter how good the developer experience around it gets. Sub-dollar payments don’t work. Agent-to-agent payments don’t work. Today’s post is about a third shape that breaks on the same rails, and the most interesting one to me, because it’s an inversion of how almost every app on the web handles money. Most apps take money from users. The one I want to walk through pays users instead. The architecture that makes that possible is small enough to fit in one post, but the economic implications are bigger than I expected when I started building it.
The app is Sats Channel, currently shipping on QuackBuilds. The premise is straightforward: you watch classic movies and television, and you earn Bitcoin (denominated in sats, the smallest unit of BTC) for the time you spend watching. There are no accounts in the traditional sense — you connect a Lightning wallet and a session starts accruing sats against your address as the video plays. The ad network running against the video pays in Bitcoin, the platform takes a cut to stay alive, and the rest is split back to viewers in proportion to attention. The whole loop is closed in BTC, which turns out to be the part that makes the math work.
Walk through why traditional rails can’t host this. A user watching a forty-minute episode might generate, very roughly, somewhere between a few cents and a few dimes of ad revenue depending on fill rate and CPM. Their share of that, after the platform’s cut, is fractions of a cent per minute. To pay that out via Stripe Connect or PayPal, you’d hit minimum withdrawal thresholds (usually a few dollars), per-transaction fees (often a fixed component plus a percentage), and KYC overhead per recipient that vaporizes the unit economics before the first payout clears. The model only works if the cost of paying a user is meaningfully smaller than the amount you’re paying them. On card rails, for sub-dollar payouts, it isn’t. The bundling tax I mentioned in the last post shows up here in its purest form — every “watch and earn” product on the legacy web ends up being a points system that converts to gift cards at $5 increments, because that’s the smallest payout the rails will tolerate.
Lightning collapses that constraint. A Lightning payment — assuming a healthy channel — costs effectively nothing to send and settles in milliseconds. Paying a user one sat is economically rational. Paying them ten thousand sats is the same cost. The accrual model can therefore mirror reality: as a viewer watches, a counter ticks upward in their balance, and they can claim that balance to their wallet by submitting a Lightning address at any time, as long as the 100-sat minimum is met. The counter only ticks while the viewer is actively watching — the player checks for engagement signals and pauses accrual if it looks like the tab is idle or the user has walked away. That’s not friction for legitimate viewers, it’s the part of the design that keeps ad revenue flowing to the people actually delivering attention rather than to a script in a hidden tab. Sats Channel sets the minimum withdrawal at 100 sats — reachable in a few days of regular viewing at current fill rates, and lower as the ad layer matures. The threshold lives in my dashboard rather than in a smart contract, so it can move down as the per-minute earn rate moves up.
The technical stack is leaner than people expect. The frontend is a video player wrapped around an attention-tracking module that emits viewing events to the backend. The backend maintains a multi-session sat balance, applies the revenue-share formula, and just requires a Lightning address to claim. The ad layer uses A-ADS, which is convenient for two reasons — it pays out directly in BTC, so there’s no fiat-to-crypto conversion to manage, and it accepts inventory from independent sites without the gatekeeping of larger ad networks. The Lightning side is straightforward to integrate via any of the standard service layers (LNbits, Alby’s API, BTCPay Server depending on how custodial you want to be). The whole thing is small enough that the interesting parts are economic and design choices, not infrastructure.
The other piece I want to walk through, because it’s a class of problem most “watch-to-earn” experiments quietly punt on, is content supply. A platform that pays for attention is only as good as its catalog, and a static catalog gets stale fast — the same hundred public-domain titles in week one are the same hundred in week ten, and viewer retention drops accordingly. The version of this product that just seemed to work in early testing was the one with a fresh playlist every time a user came back. The version that actually works at scale needs that freshness to be automated, because hand-curating a daily catalog is exactly the kind of work that becomes the single point of failure for the entire app.
Sats Channel solves this with a scraper that runs once every twenty-four hours, pulls newly available public-domain titles from the sources I’m aggregating, and populates the daily playlists automatically. The catalog grows every day without me touching it. Architecturally, the scraper itself lives on the Oracle ARM tier I covered in post two of this series — it’s exactly the kind of long-running, scheduled job that doesn’t fit serverless and that the free-tier compute layer was designed to absorb. The scraper writes new titles into a Supabase table, the frontend reads from that table to construct the day’s playlist, and a small validation pass checks each new title for playable streams before it goes live. The end-user experience is that the catalog is never empty, never identical to yesterday’s, and never bottlenecked on me being awake to curate it. The architectural experience is that one cron job replaces what would otherwise be a daily content operations problem, and the cost of running that cron is zero.
A few decisions worth surfacing because they shape the product more than they look like they should. Choosing classic content — public-domain or cheaply licensed older film and television — does three things at once. It eliminates licensing costs, which would otherwise eat the entire revenue share before any user got paid. It selects for longer-form viewing sessions, which generate more ad impressions per session than short-form content. And it attracts an audience demographic that overlaps unusually well with the early Bitcoin-curious crowd, which matters for the chicken-and-egg problem of getting the first thousand users to a platform that requires a Lightning wallet. Pricing the platform’s cut is a more delicate decision than I initially treated it as — too generous to users and the platform can’t sustain its own infrastructure, too greedy and the value proposition collapses. Making withdrawals user-initiated rather than scheduled batches keeps the trust model simple: at any moment, the user can prove the platform pays by clicking withdraw, and that proof itself becomes the strongest piece of marketing the product has.
There’s a small mechanic I built in for the early phase, which I’m flagging here because it’s the kind of thing dev.to readers tend to ask about and because it’s open to the first ten people who actually want it. Refer five friends who connect a Lightning wallet and you receive a Founder’s Badge — an original NFT showing on-chain proof you were here first. There are exactly ten of them, all ten slots are still open as of writing, and I’m reserving the option to attach perks to them later if the platform reaches the kind of scale that makes perks meaningful. I’m deliberately not over-promising what those perks will be, because I’d rather under-promise and earn the credibility back later than dangle features I haven’t built. The badge itself is the artifact; the optionality is the second-order value. The referral link surfaces in your dashboard once you connect a wallet, and progress is tracked there. If you’re the kind of person who likes being first onto something while the product is still being shaped, that’s the door.
Honest tradeoffs, because every post in this series has had a section like this and I’d be embarrassed to skip it now. Ad fill rates on small, early-stage sites are genuinely brutal, and the gap between the sats a user theoretically could earn and what they actually earn in early traffic is real. Ad-blocker penetration in the demographic this product attracts is also higher than baseline, which directly suppresses revenue. I’m currently iterating on placement configuration for a few of the secondary ad units, while the primary inventory around the player runs cleanly. And the product is in the part of its lifecycle where the economic model is sound on paper but needs sustained traffic to actually flex — the kind of bootstrapping problem that every revenue-share marketplace faces in its first months and that no architecture choice can fully shortcut.
What I keep coming back to, and the reason this build is the one I wanted to write up next, is that the inversion is real. An app that pays its users isn’t a marketing gimmick or a loss-leader funded by VC subsidy — it’s an architectural possibility that opens up the moment the payment layer can settle in fractions of a cent. There are probably dozens of products in this shape waiting to be built, and watch-to-earn is just the most obvious one. Read-to-earn, listen-to-earn, contribute-to-earn, train-a-model-to-earn — every one of these is a candidate the moment the payout side becomes economically viable, and the payout side became economically viable approximately the moment Lightning matured. Sats Channel is my attempt to build the most-legible version of the pattern. If it works, the more interesting versions come next.
You can try it at quackbuilds.com/thesatschannel. Bring a Lightning wallet (Alby works well in the browser, Phoenix or Wallet of Satoshi work fine on mobile) and pick something to watch. If you find a bug, the comments here are the fastest way to get my attention — and if you’ve thought about the same payments inversion in a different context, I’d be especially interested to hear what shape your version took.
Next post in the series is probably the failure mode counterpart to this one — what doesn’t work when you try to design products around micropayments, and the assumptions about user behavior that turn out to be wrong. Suggestions welcome on which assumptions to attack.
@itsevilduck / quackbuilds.com

Top comments (0)