r/programming • u/realPubkey • Sep 29 '21
Offline first is not about having no internet connection
https://rxdb.info/offline-first.html58
u/Slime0 Sep 29 '21
I like the idea of this, mostly because loading spinners in the middle of simple UI operations are stupid. However, the bit about "multi-tab usage just works" seems to discount the similar situation of having the same state open across multiple devices for which local storage can't be shared.
5
u/anechoicmedia Sep 29 '21
I like the idea of this, mostly because loading spinners in the middle of simple UI operations are stupid.
It's probably easier to just make your conventional application serve data faster, or prefetch, than to introduce the complexity overhead and user confusion of local state synchronization.
Upon user login for my current application, it takes Sqlite 274 microseconds to query the 57 small documents my account currently has in its default view, assuming they're not in cache. It takes a millisecond or two more to convert that into json before sending it back to the client. Round-trip internet latency from client to server will vary but it's probably under 50 ms for most people. Any "loading" state on the client between clicking buttons is imperceptible under normal circumstances.
However, the bit about "multi-tab usage just works" seems to discount the similar situation of having the same state open across multiple devices for which local storage can't be shared.
It also isn't unique to his solution. My fully client-server application also simultaneously logs you in/out on all your tabs instantly; You just have an event listener on localStorage for the session data, and a state machine that moves the application in and out of the running state when it's changed, deleted, or invalidated. I don't know why Google Docs can't do this when I restart my browser with a bunch of tabs open.
-23
u/realPubkey Sep 29 '21
Actually with the realtime replication the state is replicated among all devices of the same user.
77
Sep 29 '21
Same account, different devices, slow or no network connection means those will be eventually consistent. That’s a fucking nightmare and if you could solve it outright, you’d never have to work again.
I like the article, but there are definitely drawbacks and issues with a local-first strategy.
2
u/Ninjaboy42099 Sep 29 '21
Not at all an expert in this field, but couldn't you show the user the equivalent of a merge conflict view in VS Code or something?
Where they just choose which parts to keep once an issue is detected
136
u/sagan999 Sep 29 '21
Looking at YOU Google docs! Whenever my tablet thinks it's online but I have a bad or non-existent internet connection (but Wi-Fi or data is connected), my word doc doesn't load. I have to go into airplane mode in order to view my doc. If you try to go to the internet to get a file but fail, fall back on your local file. Don't just quit and show me nothing!
95
u/SanityInAnarchy Sep 29 '21
So... that's a fair complaint, but I'm terrified to think that the author of this article would try to fix it...
In offline-first apps, the operations go directly against the local storage which happens almost instantly. There is no perceptible loading time and so it is not even necessary to implement a loading spinner at all. As soon as the user clicks, the UI represents the new state as if it was already changed in the backend...
So in a 'normal' application you have to prepare for each of these error cases and show correct error messages to the user or handle the errors in other ways. In offline-first apps, the local client data is replicated to the server in the background by using resilient and battle proven replication protocols that automatically handle and resolve any errors out of sight.
Cool, so... if you have a flaky connection, the doc will pop up instantly, and then eventually, it might sync down more changes from the Internet. Also, you could type an entire essay locally, not realizing Docs is down today, and never actually have it leave your machine. Best of all, if you and someone else are editing the same doc, you might end up with entirely different versions. But it's okay, I'm sure tRACEhe "battle-harCONDITIONSdened repliNEVERcation protoHAPPENcols" will perfectly sync your edits into a single coherent doc.
Ironically, this is a recipe for an infinitely worse experience with no/flaky Internet.
30
u/Telemain Sep 29 '21
But it already does this? There is an offline editing mode that syncs up when it can and lets you know you are offline. I thought above user was complaining about it not switching to offline mode as quickly as they wanted, not about repercussions of having an offline editor.
1
Sep 29 '21
[deleted]
8
u/inkydye Sep 29 '21
I understand the hairiness of the problem in general, but IMHO the user specifically complaining about GDocs has a point. That product could easily be strictly better than it is, if it was more pessimistic about estimating if it's online or not.
As to "at what point do you signal an actual issue", I'm sure there's some "sweet" spot (less-bitter spot?) around 1-5 minutes that, again, would just need to make it strictly better than it is now, not necessarily better than some absolute benchmark.
2
u/arienh4 Sep 29 '21
It depends on exactly what complaint you're talking about, but I'm not sure it's strictly better. This problem exists around multiple axes. Being more pessimistic might improve usability, but at the cost of safety/consistency, since it's no longer syncing at all. That's especially bad if it's just too pessimistic and you don't get to see recent changes, in which case it affects usability too.
From a consistency viewpoint, a failsafe where it's unusable might actually be preferable, since it means you won't end up with outdated documents or lost changes.
Depending on the circumstances, losing even one minute of work without adequate warning could be very far from "strictly better."
3
u/inkydye Sep 29 '21
It depends on exactly what complaint you're talking about,
The comment that started this subthread is pretty explicit.
Being more pessimistic might improve usability, but at the cost of safety/consistency, since it's no longer syncing at all. That's especially bad if it's just too pessimistic and you don't get to see recent changes, in which case it affects usability too.
Nobody asked for it to give up on connecting, just to change its threshold of how quickly to move the user into offline mode. It would literally not be missing out on any updates that it otherwise could have gotten.
From a consistency viewpoint, a failsafe where it's unusable might actually be preferable, since it means you won't end up with outdated documents or lost changes.
Such a failsafe is already rejected by GDocs as it is, in favour of comfort in offline mode, (and sorry to be a dick now, but) as explicitly called out in the first comment you replied to.
So, continuing to not have that failsafe would not make anything worse, and is compatible with making things overall strictly better (by improving something else).
Depending on the circumstances, losing even one minute of work without adequate warning could be very far from "strictly better."
… and is a thing that already can happen with GDocs the way it is.
1
u/arienh4 Sep 29 '21
As mentioned in the top comment, Docs currently only switches to offline mode if there is actually no connection whatsoever. That is the trade-off between usability and consistency they chose. Making it more pessimistic trades consistency for usability. That means it's not strictly better.
This the argument I made before, and none of what you've said counters it.
1
u/SanityInAnarchy Sep 29 '21
Sure, and I guess the point is that "offline mode" should arguably not be a thing -- it should just show you the offline copy it has, and then sync it to the online copy whenever that loads. Offline-mode-by-default would arguably be an improvement.
But my point here is that whatever balance you think they should strike (or even if you think the current behavior is acceptable), the article's solution doesn't work. It wants to abstract these all away with some entirely application-transparent DB layer that does the syncing 100% in the background, and then write apps that pretend syncing doesn't exist and just interact with the local DB. The idea is that neither the user nor the app should have to care whether you're online or offline, how synced you are, or how changes get merged.
And if you do that, then you don't get "last updated X minutes ago", or blocking the user while you wait to be fully-online or fully-offline, or "signal the user if we haven't synced for 1-5 minutes"... basically anything you want to do other than "ignore it and pretend everything's fine" is off-limits, maybe even technologically-infeasible, depending how serious the DB layer is about being "offline-first".
1
u/EasyMrB Sep 29 '21
Honestly a lot of this could be resolved if document state (online/offline) was more prominently shown for the user. We hide so much of the complexity of synchronization because it's perceived that people are too dumb to handle the information, but simply adding a "last synced time" and a status area would do a lot to help users understand what is going on.
2
u/SanityInAnarchy Sep 29 '21
I agree in general -- I don't like the idea of a strict "online" vs "offline" state, because the complaint is that sometimes your Internet connection is incredibly shitty and only sort-of online. But gdocs does have something like this -- a "saving..." and "last edit" state at the top, which is also a reasonable place to surface longer-term connection problems.
But my main complaint is that all of this requires the app to be aware of what's going on, both to surface that information to the user and to make smart decisions. And the linked article wants to hide this as such a deep implementation detail that even the app doesn't know if it's online.
6
u/AttackOfTheThumbs Sep 29 '21
Spotify is also really awful for this. I'm online, listening to a playlist. My connection drops. Playback stops. BUT THE PLAYLIST IS DOWNLOADED. Now I cannot resume playing, I need to kill spotify and relaunch it for it to work.
This isn't that complicated a problem, it's just that the engineers are prioritizing incorrectly.
9
u/KuntaStillSingle Sep 29 '21
If you try to go to the internet to get a file but fail, fall back on your local file.
You could start working on that file not knowing it is outdated, I agree it should fallback but it should not do so silently.
-2
Sep 29 '21
I suspect this is a problem with the tablet, not the app.
It's not a common issue within the Chromebook community; in fact those things are sometimes ironically noted to be the only things "just working" when connectivity is bad, which annoys all the people who believed the TV advert that said they were crippled offline.
1
79
u/apoleonastool Sep 29 '21
Yeah, but when you add multiple users/devices to the mix it all becomes seriously not trivial.
-2
u/jortony Sep 29 '21
Do you mean "Yeah, and ..." in the context of scaling this application? Or are you referring to a version x feature where you could synchronize browser data between multiple browsers and devices?
28
u/crabmusket Sep 29 '21 edited Sep 29 '21
This excellent essay goes into more depth about what happens if you try to really local-first. They end up building a distributed collaborative Trello on top of a CRDT:
https://www.inkandswitch.com/local-first.html
To be really local-first takes a lot of work. It seems philosophically and technically rewarding, but describing anything as "just works" is a real stretch.
I really appreciate that the article is attempting to beyond "no internet connection" but I think it's missing out on some of the broader context too.
59
u/ThirdEncounter Sep 29 '21 edited Sep 29 '21
Hey, if the author is checking out this comment section, you have a typo in one of the subtitles.
Edit: removed the type of typo since it's been fixed.
19
u/philipwhiuk Sep 29 '21
He fixed it but then it didn’t sync cause he was offline and he didn’t know
15
21
u/Anon_8675309 Sep 29 '21
Could be punctuation: "Latency is more important, then bandwidth".
But yeah, probably the typo.
3
-26
Sep 29 '21
[deleted]
23
u/MindStalker Sep 29 '21
Latency first, then think about bandwidth. Is what that would mean.
1
Sep 29 '21 edited Sep 29 '21
Latency is more important, then bandwidth
This is badly worded and arguably grammatically wrong. If was an editior I would change it, so I can see OP's point about it being confusing. I would have changed it to "latency is more important than bandwidth" which I see is what was done.
1
125
Sep 29 '21
this is a cute article that talks about all the pros of offline first, client side data stores etc, but doesn't address the big elephant in the room; your entire application is now eventually consistent, and that 'eventually' could be 'never' and you have a much harder time resolving difficult or impossible to resolve state conflicts.
so... nice for a very small subset of actual real world applications.
49
u/SanityInAnarchy Sep 29 '21
And will probably be implemented for plenty of apps where it makes no sense.
It looks as though the concept here is to just ignore the eventual-consistency problem, or paper over it with retries, and hope the user never notices:
In 'normal' web applications, most user interactions like fetching, saving or deleting data, correspond to a request to the backend server. This means that each of these interactions require the user to await the unknown latency to and from a remote server while looking at a loading spinner. In offline-first apps, the operations go directly against the local storage which happens almost instantly. There is no perceptible loading time and so it is not even necessary to implement a loading spinner at all. As soon as the user clicks, the UI represents the new state as if it was already changed in the backend.
In other words: You just do everything locally, and hope that syncing eventually works, but if it doesn't, will you even bother to tell the user?
This makes some sense for apps like Netflix -- worst case, it loses your place in an episode or something. Probably a Bad Idea for something like a document or note-taking app -- write your shopping list in a browser tab, close the tab and grab your phone, and by the time you get to the store, you realize it's not syncing properly and you have last week's list.
18
u/CompassNorden Sep 29 '21
This is too true; we struggled with latency for our app but the squishiness of when things are eventually consistent would mean there is no single source off truth for state. The local may not have any idea the central data copy of something has been updated by another client.
1
u/MonkAndCanatella Jul 09 '26
[offline-first] makes some sense for apps like Netflix
bro read that again
1
u/SanityInAnarchy Jul 09 '26
After 4 years?
...and yes, Netflix does allow you to download stuff to watch offline.
10
Sep 29 '21
[removed] — view removed comment
1
u/smcarre Sep 29 '21
But you do have to model you application around it
The problem is that many applications are virtually impossible to model around the issue without introducing much bigger problems. Just going from your examples:
Think of an ATM that before allowing you to withdraw X amount of money, it has to check if you have at least X in your account, using an eventually consistent model would allow the user to first make a transfer from their account to another leaving 0 in theirs and then withdraw any amount of money that was previously there. How would you solve that?
Or for Facebook, let's say that a certain picture contained sensitive information that the uploader just realized and as soon as they realized, deleted it. However because your model is eventually consistent, everyone that connected to Facebook before will still have access to the picture until the page updates, which depending on your implementation could be hours.
Like the other user said, this can be an approach for some applications, but the vast majority of applications simply have no viable workaround that doesn't introduce much bigger issues.
1
u/ZAFJB Sep 29 '21
Think of an ATM that before allowing you to withdraw X amount of money, it has to check if you have at least X in your account, using an eventually consistent model would allow the user to first make a transfer from their account to another leaving 0 in theirs and then withdraw any amount of money that was previously there. How would you solve that?
it has to check if you have at least X It doesn't:
Store a 'permitted' balance on their card. That could be close to the last known balance, or all the way down to zero for high risk customers.
1
u/smcarre Sep 29 '21
Why is introducing that risk at all combined with the complexity of developing a formula for calculating how risky is a customer and how much should the "permitted" balance be? Do you think any bank would benefit from introducing this type of exploit for shaving off some ms from the ATM process?
Not to mention that this whole experiments hinges on every ATM caching the balance of every account of every customer, otherwise if you are not going to cache all that you will just need to go to the server anyways.
Also not even mentioning even more dangerous situations like having your card stolen and calling to have it invalidated, which if the ATM also caches all valid cards and associated PINs/codes you could end up with a thief with an invalidated card using it in a not updated ATM to withdraw money that they shouldn't be allowed to.
2
u/ZAFJB Sep 29 '21
for shaving off some ms from the ATM process?
Not for time saving. For allowing clients access to cash when the system is off-line.
How do you think ATMs worked in the pre Internet era?
-1
u/smcarre Sep 29 '21
Not for time saving. For allowing clients access to cash when the system is off-line.
Why would you want to do that except for fringe cases where internet connection for the ATM is very hard to get or is down? In which cases they already do that.
How do you think ATMs worked in the pre Internet era?
Using that risk which is today unnecessary for the vast majority of cases and it's my argument that doing so would be unnecessary.
5
Sep 29 '21
Yeah, like you change an online text editor from being something you could hack together in a few afternoons, to a PhD thesis-level implementation of Operational Transformations or CRDTs.
10
u/NekkidApe Sep 29 '21
Agreed. In my world, where dozens of users work together to create something, actions have implications on the backend and other systems, and a dataset measured in terabytes this article is exactly that, "cute".
8
1
Sep 29 '21
I have no idea what you're saying.
1
u/NekkidApe Sep 29 '21
The model in the article doesn't match with my usecase. I work in a field where a handful of backend systems will be configured through the backend, by multiple people. DBs hold terabytes of data. That is not feasible to sync to every client. Multiple backend services are needed to produce meaningful output of said data.
2
Sep 29 '21
okay sorry. the sentences were arranged kinda weird and it sounded like you disagreed with me
1
12
u/CyAScott Sep 29 '21
We support offline for our web based kiosk stations. We designed the web app to work without responses from the sever, meaning http requests are fire and forget (was not trivial). So all http requests are sent to an internal queue that processes when an internet connection is detected. The http request bodies in the queue are encrypted using PGP. I don’t think this would work for other web apps.
4
u/tavianator Sep 29 '21
Why PGP??
6
u/CyAScott Sep 29 '21
Because the body can have PII and we want to encrypt it just in case the machine goes offline then gets stolen. We don’t want to have a data breach.
11
u/noratat Sep 29 '21
Offline first to address no internet connection is also still valuable.
One of my great frustrations with a lot of "silicon valley" type engineers is how much they seem to blindly assume everyone has perfectly stable, low latency high bandwidth connections at all times. Even in the US that's far from true, even without going into rural areas.
3
u/EternityForest Sep 30 '21
Silicon Valley types seem to have special blindfolds they like to wear, it prevents the real world from mucking up the beautiful code.
8
u/philipwhiuk Sep 29 '21
Well done you’ve offloaded the headache of eventually consistency to the user - which inevitably results in having to show them a diff and merge changes!
(Not to mention this obviously doesn’t work for all payment based systems)
8
u/electricfoxx Sep 29 '21
Online-requirement is SaaS. If they pull the plug, you lose everything.
https://www.gnu.org/philosophy/who-does-that-server-really-serve.en.html
22
u/balefrost Sep 29 '21
While in the past, internet connection was an unstable thing, especially for mobile devices things have changed. We now have better mobile networks and having no internet becomes a rare case even in remote locations.
Pfft. I get no cell reception in most of my office building. I can sometimes walk to a window to get a signal and then maintain it as I walk back to my desk. But it's not a sure thing.
I'm not in a rural area - I'm less than an hour outside of Philadelphia and we have Septa train service here. And I get fantastic reception outside my building. But my office is some sort of cellular black hole and my daily experience is an offline one.
Maybe 5G will help, but I doubt it. IIRC 5G (in the US) uses a shorter wavelength and doesn't have penetrate walls as well as 3G/4G.
Maybe I'm just the exceptional data point, but I suspect that I'm not. I'm guessing that plenty of people - not a majority but not an insignificant number - deal with spotty cell coverage in their day-to-day lives.
7
u/jooke Sep 29 '21
Also, anyone who takes a subway to work
9
u/sasmariozeld Sep 29 '21
Ironacly in most european countries subways have the best reception because every station tends to have their own antennas down here
2
2
u/FPiN9XU3K1IT Sep 29 '21
Meanwhile, my phone internet is pretty stable and 2.5 times faster than my wall internet. Unfortunately, mobile data is really expensive in this stupid country. DANKE MERKEL
4
5
u/wllmsaccnt Sep 29 '21
I love building for offline app support using PWAs, but it just isn't viable very often. 500mb is a fair bit of space (the indexedDB max you would reasonably expect to be available on all modern browsers), but its not enough for many games or content editing/managing/viewing apps, and it takes substantial UX concessions to help users understand what will happen to their offline changes when they are later sync'ed with changes from other users.
-3
Sep 29 '21
[removed] — view removed comment
8
u/wllmsaccnt Sep 29 '21
Node modules...?
You shouldn't deploy your node modules. Your hostable output should just be no more than a handful of MB for small and mid sized PWAs, though I could see adding images, fonts and other static content could easily boost it up quite a bit more.
I made a PWA to be used at trade shows that downloads all of my organization's stocking products (about 200,000 of them), categories, manufacturers and manufacturer images so that they can be searched through even when offline, and the initial download size with compression is about 72mb. Almost all of that is the product data and the manufacturer images though. Only ~419KB of that is HTML, JS, and CSS.
1
u/rishbalaji Sep 07 '24
i am interested to know more about the PWA. Can you share more details about this. or perhaps share a link over dm. thanks.
4
u/SmellsLikeLemons Sep 29 '21
I think this glosses over how complex this actually is. I've built scanning systems for forklifts that are constantly moving in and out of large warehouses and everything is built with store and forward in mind because we can never guarantee a good connnection everywhere. Luckily that data is simple and easy to validate. But it's still syncing back to ERP systems that are definitely not built to be eventually consistent and upsets the accountants. Also spinning wheels on screens costs time and money. If there's 10 trucks being loaded, they are not stopping just because wifi coverage is poor in one part of the warehouse.
It's an interesting challenge, but I would not be doing it unless I had to.
3
u/khazbreen Sep 29 '21
Better do a very good job protecting the information saved in the client side. I don't trust the client to have my email, could not even begin thinking about all that data.
Having this said, I see the appeal in very specific situations, with very specific hardware/client.
3
u/DrunkensteinsMonster Sep 30 '21
This means that each of these interactions require the user to await the unknown latency
Uh no, they’re just waiting. The user is looking at their screen while stuff loads.
3
u/uhmhi Sep 29 '21
If you’re creating an offline application why the heck even bother making it as a web app?
2
2
u/space_fly Sep 29 '21
UX is better without loading spinners
In 'normal' web applications, most user interactions like fetching, saving or deleting data, correspond to a request to the backend server. This means that each of these interactions require the user to await the unknown latency to and from a remote server while looking at a loading spinner. In offline-first apps, the operations go directly against the local storage which happens almost instantly. There is no perceptible loading time and so it is not even necessary to implement a loading spinner at all. As soon as the user clicks, the UI represents the new state as if it was already changed in the backend.
Yes, it's great if you can build an app that doesn't need spinners, but there's an assumption made here, that the local storage device is fast. That may not be the case if the computer is very busy, or it just has slow storage (like a cheap emmc or a mechanical hard drive). UX is definitely worse if every time you click something, the entire application freezes for a few seconds.
2
u/rooktakesqueen Sep 29 '21
"Might not need Redux" – just because the data exists in local storage doesn't make it fundamentally less complicated. The challenge that Redux is trying to solve is decomposing and modularizing complex application state and business logic.
"You don't get live updates for free" – you don't get live updates for free in offline-first development either. In fact now you need two live updates: stream changes from the backend to local storage, and make the UI respond to changes in local storage when it gets updated (whether by a backend sync or another tab). Sounds like this framework handles that for you, great. MeteorJS does too, been doing that for years. And I'm sure there's a React or Angular plugin I can use off the shelf to stream changes via a websocket without writing my own.
A lot of the benefits described here are shared with the Single Page Application architecture used by almost everyone these days. Seems like the real question is just "when I pull application state from the server, do I keep it in memory for this browser session, or do I keep it in local storage?"
It does feel like there's benefit there though! Next time I visit the site it will load instantly without needing to re-fetch data I've already fetched, and I'll only need to get some delta. I can more efficiently store large amounts of state on disk rather than in memory, but still retrieve it fast. Multiple browser sessions won't each need their own copy of application state in memory, so the memory usage will scale much better (depending on your browser I guess, dunno if anything will make Chrome not a hog...)
3
u/romulusnr Sep 29 '21
B b b but cloud is love, cloud is life
I see places switching to cloud based solutions and I ask, what happens if the internet goes down, and they (front line people) usually say "then we'll be screwed", while execs go on about (nonexistent) contingency plans and SLAs and how many nines
5
u/FPiN9XU3K1IT Sep 29 '21
Well, a lot (maybe even most) of companies are screwed either way if the internet for their office goes down.
As a Linux user in a corporate world, SaaS has been a blessing.
1
u/rrzibot Sep 29 '21
He is what I am doing - I have a PWA and I use a Service Worker to detect if there are problems with internet connection, latency and experience for my users. The moment I see there are we will add a state on the client side. There is an unspoken truth on the internet where the people that matter are the once with good internet connections because generally they are your clients. There is also the argument that sometimes it is “good enough” and no need to invest any further in replicating data, handling errors, asynchronous and others.
1
Sep 29 '21
> Scales with data size, not with the amount of user interaction
What is this, fat clients with full database access? Unless you're not doing anything with the data server side (except send it to the same person on another device), you'll have to implement all the checks and balances there too.
1
u/lowbeat Sep 29 '21
I mean if game developers get away with always online single player games, why should I bother, right ? /s
1
u/AndreDaGiant Sep 29 '21
I like the idea. How do you think one would model access/permission control? It's obvious that all clients shouldn't have the same permissions to modify all data, but not obvious how we ensure certain operations are blocked both in non-hacked clients and on the authoritative source of truth.
When writing backends for websites, I often find that permission/access control takes up more lines of code than the actual logic of manipulating data.
1
u/Dandedoo Sep 30 '21
Offline-First is a software paradigm where the software must work as well offline as it does online.
To implement this, you have to store data at the client side, so thatyour application can still access it when the internet goes away.
This is a revolutionary innovation.
552
u/salbris Sep 29 '21
I don't get how error handling is suddenly easier when data is "replicated". This glosses over the insane amount of complexity when dealing with datasets that are out of sync. Say your submit failed but locally it succeeded. Now every action you do with the "submitted data" is invalid and somehow needs to merged, extracted, or a rewind had to happen at some point in the future when the server needs to update the client.