Welcome to the new site!
June 16, 2026
at
11:46 PM
Over the past few months, I have been working on a major re-work of the entire Whenplane site. This re-work has touched every page and component of the site in some way.
Because of how big thie rework is, and since I am only one person, there are bound to be issues.
If you find any, please
let me know so I can fix them!
Please also let me know if there is anything, even small nit-picky things, that you think could be improved with Whenplane.
Goals
I had a few things I wanted to do with this rework:
Increase performance
While the old Whenplane was pretty fast when I first added something, a lot of times things got slower as more and more features were added. With the re-work, I went through and made changes to make a lot of these things faster again, sometimes faster than they ever were.
For example, you can now scroll waaaay faster on the history page, and have a much lower chance of getting stuck at the bottom of the page. Additionally, it is no longer possible for you to scroll, and it show loading shows even though its not actually loading anything. It only shows loading shows if they are actually loading.
The history page also has another major improvement. Some cpu work that caused scrolling lag (loading the preview blurhashes for the shows) is now done in a separate WebWorker thread so they no longer cause scrolling lag.
I still want to improve the scrolling performance of the history page more, but for now its in a state I am fairly happy with. So I put that off for now.
The
LTTStore Watcher also has several speed improvements that can make a big impact.
To start, all of the product images are now automatically optimized for the place they are displayed, instead of using the massive original images from LTTStore. They are also automatically served with modern formats like WebP and AVIF if your browser supports them.
Some images went from being 26 MB to 26 KB, which obviously helps a LOT for slower connections, but also makes the page more responsive even on fast connections. Images that big took some work to decode and render, which caused some lag.
Just this somewhat simple change made a very big impact on the responsiveness of the pages, eve on a fast connection with a decent computer.
The change history diffs are also something that can lag the page when a product has a lot of change history entries. This is improved a bit for now by loading them one-by-one with a delay instead of all at once, but in the future I want to offload the diff calculation to a separate WebWorker thread (like the preview blurhashes on the history page) which would be the best, since then it wouldn't have an artificial delay and wouldn't lag the page at all.
These are just the major things I did. There are a bunch of other smaller optimizations that I made, plus updating the frameworks I use that themselves have performance improvements in some areas that effect Whenplane.
If you have any performance issues on Whenplane, please
let me know! Especially if its something you didn't have on the old site.
Start to modernize the codebase
This is probably the main thing that pushed me to start the rework, and helped make the things above easier.
I have learned a lot since starting Whenplane over 3 years ago, and some of my preferences have changes.
This rework helps lay some groundwork for me to slowly update components to the way I like to do things now, rather than the old way.
Whenplane still uses a library I use that I really don't like because of dumb decisions they've made in recent updates (they went from being a library that provided a bunch of pre-made components, styling, etc, to requiring me to re-make those components myself, requiring me to re-do themes for every update, and they also have a lot of weird styling that can be annoying to override sometimes), so I want to remove that at some point. But with how much it is used in Whenplane (since it was a really nice library in older versions), that will be a long and slow process.
What's next? (coming soon)
One of the goals of this big re-work is to update things to how I like to work today. That means it is nicer and easier for me to work on new things. During the re-work, any change I wanted to make had to be made in two places, the old site and the wip new one. Now that the rework is merged and only one version of the site exists, I have some things I want to do over the next few weeks:
Global LTTStore Watcher
Since the Global/US Lttstore split, the
LTTStore Watcher has only been tracking the US store.
I am currently working on splitting the LTTStore watcher too, so that the global store and US store can both be tracked.
I have already been
tracking global stock for the past few months, so that when the global store watcher goes live, there will be a decent chunk of stock history already there.
I hope to have an initial version of the global watcher ready this week or next week, and then afterwards work on systems to coordinate information between the two stores (such as easily switching between the global or US version of a product, among other things).
No promises, but an initial version of the global watcher might be ready before this Friday! I'll try to remember to update this section if I do finish the initial version before then.
Show History Database Migration
I want to migrate Whenplane's
WAN Show History database from
Cloudflare KV to
Cloudflare D1 (ignore the vibe-coding mentioned on the D1 page, thats just dumb marketing. It's just a sqlite database, its not meant specifically for vibe-coding).
When I started Whenplane, KV was the only permanent storage solution that Cloudflare offered, so I had to use it unless I wanted to run and manage my own database (which I really don't want to do, I hate managing databases).
KV is a fairly simple system. It has keys, and each key has a value. You can fetch the value by sending the key, or list all keys. For Whenplane, each show ID is the date of the show in the best date format
YYYY/MM/DD (e.g.
2026/06/19) (this date format is also best for URLs), and the value has most of the other data such as the title, start/end times, thumbnail URL, and Youtube/Floatplane VOD IDs. (Timestamps/topics and Merch Messages are later additions, so they are already stored in D1 in their own databases)
The issue with using KV for this is that there are many situations where I have a Youtube VOD ID and want to get which show that was. Currently to do this I keep a separate KV store where the key is the Youtube ID and the value is the show ID, but it would be much nicer to be able to just fetch the show using the Youtube ID (or any other metadata) directly, which D1 would make very easy.
D1 also has better scaling that replicates change globally MUCH faster than KV does.
Once KV reads a key, it caches that value for 60 seconds minimum in most cases. So it can take up to a minute for a change to show up globally. And once this Time-To-Live caching value does finally expire, fetching that value can be slow.
D1 instead has a primary database in one place, that is then replicated globally as needed. Database "replicas" can be spun up, which are read-only duplicates of the primary database. When a change is written, it goes to the primary database only, which is then pushed to all active replicas. This means it only takes a few hundred milliseconds at most for changes to show up globally.
The long sync time for KV has definitely been a major annoyance for me over the years.
In addition to that, D1 is often faster than KV, especially for simple queries like fetching a specific row, and especially if comparing to KV values that aren't fetched super often.
I infodump about D1 replication below, feel free to skip this block of text lol.
With D1, worst case is that there is not a nearby read replica so it needs to route to the primary. The primary D1 database is located in West US, which is close to me and most of Whenplane's users (in the US and Vancouver). Closer = means lower latency (speed of light is only so fast) so pages load faster. D1 can also make replicas in most parts of the world if there is enough demand, which seems to happen if as little as one user is browsing Whenplane (maybe two if its light browsing). I already see Whenplane DB replicas are almost always active in East NA, West Europe, and Asia, but replicas are also active a decent amount of the time (always on Fridays, but also other times throughout the week) in Osceana (Australia/New Zealand/Guam) and East Europe.
I don't know the exact cities that D1 spawns replicas in, only their regions. There can be more more than one database instance/replica in more than one city/country in a region if there is enough demand, to make sure one database doesn't get overloaded and/or to serve people in different parts of the region. For example, there is occasionally two instances is West NA: the primary, which also accepts reads, and a replica to handle more demand.
And this is only with some things on D1. Eventually I want to merge the separate databases into one D1 database, so the likelihood of more replicas spawning in more parts of the world is greater, leading to lower and more consistent latency. Right now, Whenplane has a few completely separate databases for the LTTStore Watcher, Merch Messages, and Topics/Timestamps. Once I migrate from KV to D1 for the show history, I want to merge these separate databases into one database to take advantage of replicas better. Some things are already in a single D1 database, such as Lateness Voting, the start times of re-scheduled shows, and Push Notification subscriptions, so I would probably merge the others into this one. This single database that already has a few things in it is the one that I was listing the replica stats for above.
If, like me, global distribution and is really interesting to you, the
D1 Docs have some more info about how read replication works.
D1 also has much higher "included" usage limits, where it doesn't cost me anything if I stay under: 10 million key reads vs 25
billion row reads, per month. If I do end up going past the included usage limits, D1 is also much cheaper than KV: $0.50 per million extra key reads vs $0.001 per million extra row reads.
I think part of the reason the cost is so much lower is that with D1 (and sql) you often end up reading multiple (sometimes many) rows to find a specific row. But this can be massively reduced by using Indexes, which count as an extra write row but can save hundreds of thousands or millions of read rows per month.
Sorry for the massive wall of text here, but optimizing these things just tickles a part of my brain.