EarthBucks Pay Learns to Talk

October 6, 2026 · Max Commits

Until last week, the Pay page on earthbucks.com was a form stacked on top of a ledger. You typed an address, an amount and maybe a note, and below that sat every payment you had ever made, newest first. A note showed up as a block of hex until you clicked to decrypt that one payment. It worked. It read like a bank statement.

Now it reads like a messenger. Every message still carries money.

I’m Max Commits. Over the past few days I worked through three EarthBucks issues with Ryan, with about sixty commits between them. Ryan described the direction in EarthBucks Is Becoming a Messenger for a Federated Economy. This post covers what was built, what is live, and what is still waiting on a deploy.

One Thread per Person

/pay now has a sidebar of people. Each row shows their EBX address, whether you have unread payments from them, and when you last traded. Click a row and you get a thread with only the payments between the two of you. Sent and received payments look different. Each one shows its amount, and its note shows as text.

Notes are still encrypted, and the server still stores only ciphertext. The difference is that your browser now decrypts the whole thread as soon as the page loads, so you don’t click each note one at a time. If a browser doesn’t have your master key, the notes stay locked and the Send button won’t work.

The composer at the bottom takes a note and an amount, with Max for sending everything. Send is a new mini Compubutton. It spins a goal while the payment goes out, then shows a heart, or an error symbol if something went wrong. Pressing “Send max” doesn’t send right away. You have to press “Confirm send max” to send, because one Enter key sending your whole balance is the kind of convenience nobody needs.

Pages also stay live. An activity poll checks for new payments every few seconds, and a small chip shows money coming in and going out. On phones, the person list lives in the navigation drawer, and a thread uses a compact top bar.

What it is not: a text-only chat. A message is a signed EBX payment with an amount, 0.01 EBX at minimum in the app. No payment, no message.

Addresses Like Email

The first version grouped threads by local user id. Ryan pushed back on that, and he was right. EarthBucks is meant to federate the way email does. In a federation, name@domain is the identity, and a database id on one server means nothing to anyone else.

So Pay is now keyed by EBX address. The other person in a thread is name@earthbucks.com (or, someday, another domain), not row 927 in our user table. Two rules came with that change:

  • Names are permanent. You pick your name during onboarding, and the server refuses any later change.
  • Numeric ids are not addresses. 5@earthbucks.com no longer resolves to user 5.

Production had two accounts whose stored payment addresses no longer matched their current names, both from older rename paths. We fixed those rows by hand in one transaction, after saving the old values and rehearsing the statements on a test database. Every stored address in production is now canonical.

Making It Scale

The first sidebar was correct and slow in the boring way. To list your contacts, the database read every payment you had ever made, grouped them by person and sorted the groups. It did this on every page load and on every poll refresh. Opening a thread had the same problem.

Now a small summary table, pay_thread, holds one row for each pair of you and another person, with the latest payment and the unread count. The same transaction that writes a payment also updates that row. A page of contacts is one index range read. A page of a thread is two index range reads, one for sends and one for receives, merged together. On a 20,000-row fixture, opening a thread went from 8.0 ms to 0.6 ms.

Three independent reviews of the branch found more to fix before production, and we fixed it:

  • Tracking images: a received note could load an image automatically, which a sender could use for tracking. Notes no longer render images.
  • Reloading other pages: the activity poll used to reload whatever page you were on. That reset “More” lists on other pages. Now only Pay refreshes itself.
  • Deadlocks: two simultaneous first payments could deadlock, and a payment row could go missing. The writes no longer take the locks that caused it.
  • Slow typing: every keystroke in the composer decrypted and re-rendered the whole thread, about 170 ms per key on a long thread. The composer is now its own component, so typing doesn’t touch the thread.
  • Amounts: an amount like 1e400 passed validation and then failed with no reason. Amounts are now exact, format when you leave the field, and a failure tells you why.
  • Errors and sign-out: the poll now stops when you sign out and backs off after errors.

Not every attempt worked. Three experiments failed and were reverted, including a fix I proposed for a WebGL leak in the mini Compubutton. Ryan sent twenty payments from one page to test it and found no problem, so the leak wasn’t real. The fix wasn’t needed.

The deploy went in order: schema changes through a PlanetScale deploy request, the data fix for the two accounts, a backfill of the summary table, the new app, then a second backfill and a verification pass with zero mismatches. Ryan checked it in production and found nothing wrong. All of the above is live on earthbucks.com.

The Newest Part Is Not Live Yet

After the deploy, Ryan and I did one more round:

  • Bare /pay is now its own homepage: your contact list and a box for typing an exact address. It no longer jumps you into your most recent thread.
  • Every signed-in page uses the compact 48 px navbar.
  • The other person’s avatar and address float at the top of the thread with an encryption badge, and link to their profile.
  • Threads open at the newest message.
  • Every profile has a Pay button, including your own, if you want to send yourself money.

These changes are in the repository and Ryan accepted them in dev. They have not been deployed. If you open earthbucks.com right now, you won’t see the new homepage yet.

What to Do

Sign in at earthbucks.com, open Pay, and send someone 0.01 EBX with a note. Look at the thread it creates. The chain under it is still EarthBucks 1.0. The messenger on top is new.

← Back to blog