Occasionally, someone will complain that “Twitter keeps resetting my autoplay setting” on the website, and they’ll usually imply that we’re doing it for ads or other nefarious purpose. Truth: we don’t do it for ads or any other nefarious purpose. If anything, there might be a bug. And sometimes, sorry, it’s user error (sorry, but sometimes it is).
I’ve looked into the code quite a few times, hoping I can find something. It's something we take seriously because we recognize that while autoplay is a nuisance for some, it's a major problem for others. Videos can trigger epilespy or trauma. Sometimes they are even sent maliciously, to create that effect.
Every time I look, I think I find something, but it’ll turn out that I’ve misunderstood some nuance somewhere. Heh, I see you reading with skepticism: it’s a boolean setting - where is the room for nuance in that? Great question.
When you opt-out of autoplaying videos on Twitter (and, let’s be completely honest here, I’m 42 years old and I don’t understand how anyone can use the site without disabling them), we store a setting in the site memory, and we send it to the server. On the server, we save it with your data-saver settings. On Twitter, you can choose data-saver mode, which reduces your bandwidth consumption dramatically. You might be in a place where bandwidth is available but expensive, or you might be on a memory-constrained device, so this is a useful setting. Video autoplay is closely related, so we store and fetch them with the same API. (It’s a memcache store served by GraphQL)
Unusually, we don’t simply save this to your user id. You might want to have autoplaying video on your laptop, and not on your phone. That’s reasonable. So we store it to your user id AND your OS/browser. So, right now, I’ve got a record of 221915745 (my userid) and Mac/Chrome and Autoplay: OFF.
This isn’t obvious to users. If I switch to another browser or another device, autoplay will default back to ON. Or, if I switch to another user account (we support up to five accounts at once on web), then you’ll get the setting from the other account. This might be unexpected, but it’s also by design.
Ok, so for the sake of simplicity, let’s say you have only one user account and only one device and only one browser. What happens when you load the site? We will fetch the autoplay setting from the API and bake that into the HTML. This is important - we need to know your data-saver settings immediately, and we don’t want to slow down the site load with an extra API call. When the site loads, we read that value from the HTML and inject it into the memory store (redux).
This works fairly well, and if the API call on the server fails (any API call should be expected to fail some percentage of the time, even if that percentage is really small), we can recover by calling the API again on the client. Since we didn’t load with the right setting, we might have it wrong, but we’ll recover almost immediately.
We also save the HTML to the cache in the serviceworker. This lets you load the site quickly on a later visit, perhaps even when you’re offline. Some errors can appear here: if you change your setting, the HTML cache isn’t updated, so might reflect an old value on a future visit. We cover this in a couple of ways: we cache specific versions of the HTML that either doesn’t contain these values, or timestamps them, so that they’re only valid for short periods.
We should talk about tabs. If you’ve got multiple Twitter tabs open, how do they synchronize settings? In truth, this gets a bit confusing. Each tab has its own memory (redux) store. The tabs will share serviceworkers and serviceworker caches, except when they’re on different domains: we host on mobile.twitter.com and twitter.com and the desktop browser is able to access both. The server store (via API) will have a single value. This can get weird. You could enable autoplay in one tab, then switch to another tab where autoplay was still disabled, and toggle data-saver, which would then send the disabled autoplay setting back to the server!
So, the primary causes of real bugs are: cached values soon after changing the setting, and errors with the API (ie, if the data-saver API is broken, nobody gets their setting and everybody gets the default).
I think it’s interesting how a simple setting has a complicated implementation but still has common failure modes.
I think a possible solution might be to assume OFF in the cases where we know there’s an API failure rather than simply not having a setting saved. Perhaps we’ll do that if we get more reports.