Offline-first apps promise instant loading and privacy, but in practice, very few apps get offline support because getting sync right is surprisingly hard.
Offline-first apps sound like the future: instant loading, privacy by default, and no more spinning loaders on flaky connections.
But in practice, very few apps get offline support right. Most simply queue changes locally and push them when the network comes back (spoiler: this doesn’t really work). Eventually, users see a scary banner saying “changes may not be saved.”
The reason is simple: syncing is hard.
When you build a local-first app, you’ve effectively created a distributed system. Multiple devices can mutate data independently, sometimes offline, and later must converge to the exact same state without losing data.
There are two main challenges to solve:
Unreliable ordering
Conflicts
Let’s go through them.
In a distributed environment, events happen on multiple devices at different times. If you just apply them as they arrive, you get inconsistent results.
Example:
Device A sets x = 3
Device B sets x = 5
Both happen while offline.
When the devices sync, the final value of x
depends on which update is applied first. That’s a problem.
Traditional backend databases solve this with strong consistency, but that requires global coordination—too slow and brittle for local-first systems.
Instead, we want eventual consistency: every device applies changes independently but eventually converges to the same result once all changes are known.
The challenge is figuring out the correct order of events without relying on a centralized clock (because the network might be down).
Surprisingly, there’s a simple solution to this seemingly hard problem: Hybrid Logical Clocks (HLCs).
HLCs generate timestamps that are:
Comparable (can be sorted lexicographically)
Causally consistent (encode the order in which events happened)
HLCs combine two pieces of information:
Physical time (from the machine clock)
Logical time (a counter that increments when clocks are out of sync or events happen too close together)
In plain terms, HLCs let devices agree on “what happened first” without perfectly synchronized clocks.
Imagine two machines, A and B:
Machine A records an event at 10:00:00.100
.
→ Its HLC becomes (10:00:00.100, 0)
(time + counter).
A sends a message to B with this HLC.
Machine B’s clock shows 10:00:00.095
(slightly behind).
When B receives the message, it advances its HLC to at least match A’s timestamp.
B’s HLC becomes (10:00:00.100, 1)
— the counter increments to indicate this happened after A’s event.
Result:
Event on A: (10:00:00.100, 0)
Event on B: (10:00:00.100, 1)
Even though B’s physical clock was behind, we can now order events consistently across machines.
Even with proper ordering, conflicts still happen when two devices modify the same data independently.
Example:
Initial balance = 100
Device A: +20
→ balance = 120
Device B: -20
→ balance = 80
When they sync, which value should “win”?
If you naively apply both updates, one overwrites the other—losing user data.
Most systems ask developers to write manual conflict resolution code, but that’s error-prone and hard to maintain.
The right approach is CRDTs (Conflict-Free Replicated Data Types).
CRDTs guarantee two important properties:
Commutativity: Order of application doesn’t matter
Idempotence: Applying the same change twice has no effect
This means you can apply messages in any order, even multiple times, and every device will still converge to the same state.
One of the simplest CRDT strategies is Last-Write-Wins (LWW):
Each update gets a timestamp (physical or logical).
When two devices write to the same field, the update with the latest timestamp wins.
Example:
Device A: balance = 120
at 10:00:00
Device B: balance = 80
at 10:00:02
When syncing, the system keeps 80
because it was written last.
When building a local-first app, you need a rock-solid local database. SQLite is the obvious choice: battle-tested, lightweight, and available everywhere.
That’s why we built our local-first framework as a SQLite extension.
Our approach (simplified):
Every change is stored as a message in a messages
table with:
timestamp
(from HLC)
dataset
(table name)
row
(encoded primary keys)
column
value
Applying a message is as simple as:
Look up the current value
If the incoming timestamp is newer → overwrite
If it’s older → ignore
This guarantees convergence across devices, regardless of the sync order.
This architecture makes syncing simple and reliable:
Reliable: Survives weeks of offline use without data loss
Deterministic: Final state always converges
Minimal: Just a small SQLite extension, no heavy dependencies
Cross-platform: The extension is available for iOS, Android, macOS, Windows, Linux, and WASM
Stop faking offline support with request queues
Embrace eventual consistency
Use proven distributed-systems techniques like HLCs and CRDTs
Keep it small and dependency-free
The result? Apps that are instant, offline-capable, and private by default — without the complexity of traditional client–server synchronization.
If you need a production-ready, cross-platform, offline-first engine for SQLite, check out our open-source SQLite-Sync extension.
> The Solution: CRDTs. The right approach is CRDTs (Conflict-Free Replicated Data Types)... This means you can apply messages in any order, even multiple times, and every device will still converge to the same state.
This is very much "draw the rest of the owl".
Creating a CRDT model for your data that matches intuitive user expectations and obeys consistent business logic is... not for the faint of heart.
Also remember it turns your data model into a bunch of messages that then need to be constantly reconstructed into the actual current state of data. It's a gigantic enormous headache.
Almost every time I see CRDTs mentioned it’s used as a magic device that makes conflicts disappear. The details, of course, are not mentioned.
Technically an algorithm that lets the last writer win is a CRDT because there is no conflict.
Making a true system that automatically merges data while respecting user intent and expectations can be an extremely hard problem for anything complex like text.
Another problem is that in some situations using a CRDT to make the conflict disappear isn’t even the right approach. If two users schedule a meeting for the same open meeting room, you can’t avoid issues with an algorithm. You need to let them know about the conflict so they can resolve the issue.
> Technically an algorithm that lets the last writer win is a CRDT because there is no conflict.
Yes. It’s called a LWW register in the literature. Usually a MV (multi value) register is more useful. When there is a conflict, MV registers store all conflicting values and make any subsequent reader figure out what to do.
But for my money, usually what you want is something operation based. Like, if we both append to a transaction list, the list should end up with both items. Operation based CRDTs can handle any semantics you choose - so you can mix and match different merging approaches based on the application. And the storage for LWW and MV is the same, so you can start simple and grow your app as needed.
IMO the reason local first software is still not popular is the same reason encrypted messaging apps took awhile. There’s a lag from good CS research enabling a class of applications and good implementations being available with good UX. Most CRDT implementations are still pretty new. Automerge has been really slow until quite recently. Most libraries don’t support ephemeral data or binary blobs well. And there aren’t a lot of well defined patterns around user login and authentication. Local first apps today have a lot of work ahead of them to just exist at all. Give it some time.
The details appear to be not giving a damn about changes to data. I personally wouldn't describe that as "converging". As it says, this is "Last Write Wins", which is great if the last writer is always correct.
"If it’s older → ignore" -- yea, I guess that's a solution but I would really have to look for the problem.
I've gone down this road and considered github (or similar) as the backing database. In the end, I just don't have an answer that isn't specific to nearly every field that might be entered. A notes field might be appended. First in might be important, or last in (if it can be trusted as correct). Usually it's something like, "which of these two did you meant to capture?"
Funny thing is that the article gives an example where "last write wins" is quite clearly a bad solution.
Balance = 100 A: balance = 120 B: balance = 80
Clearly, these are transactions, and it doesn't matter in which order they're applied, but it does matter that they're both executed. End balance should be 100, not 80 or 120.
I was thinking about this overnight and maybe my beef is the article feels like it's written as a solution to "offline", when really it's a much narrower solution.
This solution doesn't nearly move us toward making local-first apps more popular, which was nominally the theme.
I’ve never really thought about this - how does Outlook handle this? Has anyone received a “sorry, that room you reserved actually wasn’t available; talk to this other dude who reserved it too” message after reserving a meeting room?
Or does it just double book the room? Or is there a global lock on any transaction affecting a meeting room, so only one goes through? (Feels like it doesn’t scale)
In Google Workspace, rooms are resources with calendars that can be configured to auto accept any invitation unless they’ve already booked. So it’s basically first come first serve. Even if two people are literally trying to book the room, at the same time, simultaneously, one request will go through first and will be accepted and the second will be declined. I imagine outlook is similar.
In other words, Google sacrifices availability/latency here - they don't accept the request until they can be sure it's still available.
They can accept the request (accept as in receive for processing).
They just can't send the acknowledgement of "succesfully booked" yet.
> Or is there a global lock on any transaction affecting a meeting room, so only one goes through? (Feels like it doesn’t scale)
Why wouldn't it scale? How many meetings are booked per second in your organization???
I think the potential for abuse is high. With a locking system, someone could (and probably would) click (manually or with a script) on a time slot to "reserve" a room just in case they needed it.
These are physical meeting rooms within a company. The resolution to this sort of abuse doesn't need to be automated, first it's a person in the facilities team having a quiet chat with the person doing that and asking them not to, eventually it gets escalated through various managers until it's a very final chat with HR before being asked to leave the building and not come back.
And if they did it a lot, they're scolded or fired.
That's not a real problem - at least not in the "book a corporate meeting room" space.
Clearly you fell for the premature measuring fallacy, everyone knows to optimize for web-scale first.
Exchange server accepts or rejects meeting requests. There's no offline room reservation so it's pretty simple.
Then it does whatever is needed to make it safe. For example, it might use a hash ring to assign each meeting room to a single node, and that node processes one request at a time. Most distributed systems are like this.
A traditional database funnels all your data changes down to one leader node which then accepts or rejects them, and (if A+C in the case of single node failure is desired) makes sure the data is replicated to follower nodes before accepting.
A distributed database is similar but different pieces of data can be on different leaders and different follower sets.
This comment was rate-limited.
> I’ve never really thought about this - how does Outlook handle this?
Simple: It’s server based. These problems are trivial when the server is coordinating responses and the clients can only reserve a room if the server confirms it.
This is the problem that gets hand waved away with local first software that has multi user components: It doesn’t take long before two users do something locally that conflicts. Then what do you do? You have to either force a conflict resolution and get the users to resolve it, or you start doing things like discarding one of the changes so the other wins.
It doesn't scale universely, but it doesn't need to: it only needs to cover a specific company/organization/department. So it's trivial to work at that scale.
Hell, it's so feasible, it can even done manually IRL by some person (like discussions where a person holds the "talking stick" and only there are allowed to speak until they pass it to another person - that's a lock).
You can resolve it with an algorithm, like so
- prefer seniority - prefer pay scale - prefer alphabetical - roll dice
That’s how a business would probably do it since the first two alone align with how the business already values their Human Resources, which would translate to “the objects that the Human Resources compete for”
and the interns get the blame for what they can't book why rooms, but for the people managing them it's just so easy.
Incorrect.
In a well designed system, the intern will be delegated with “room booking authority” on behalf of their most senior manager on the calendar invite.
Using something like this, that would be in the CRDT resolution algorithm.
https://w3c-ccg.github.io/zcap-spec/
Company culture will recognize it is an HR problem.
> Technically an algorithm that lets the last writer win is a CRDT because there is no conflict.
Your comment shows some ignorance and a complete misunderstanding of the problem domain.
The whole point of CRDTs is that the set o operations supported is designed to ensure that conflict handling is consistent and deterministic across nodes,and the state of all nodes involved automatically converge to the same state.
Last-write-wins strategies offer no such guarantees. Your state diverges uncontrollably and your system will become inconsistent at the first write.
> Making a true system that automatically merges data while respecting user intent and expectations can be an extremely hard problem for anything complex like text.
Again, this shows a complete misunderstanding of the problem domain. CRDTs ensure state converges across nodes, but they absolutely do not reflect "user intent". They just handle merges consistently. User intent is reflected by users applying their changes, which the system then propagates consistently across nodes.
The whole point of CRDTs is state convergence and consistency.
I think the parent was complaining about mentions of CRDTs which don’t acknowledge that the problem domain CRDTs work in is very low level, and don’t mention how much additional effort is needed to make merging work in a way that’s useful for users.
This article is a perfect example: it says syncing is a challenge for local-first apps, logical clocks and CRDTs are the solution, and then just ends. It ignores the elephant in the room: CRDTs get you consistency, but consistency isn’t enough.
Take a local-first text editor, for example: a CRDT ensures all nodes eventually converge on the same text, but doesn’t guarantee the meaning or structure is preserved. Maybe the text was valid English, or JSON, or alphabetized, but after the merge, it may not be.
My suspicion, and I might be going out on a limb here, is that articles don’t talk about this because there is no good solution to merging for offline or local-first apps. My reasoning is that if there was a good solution, git would adopt it. The fact that git stills makes me resolve merge conflicts manually makes me think no one has found a better way.
There is definitely no general solution but for some domains there may be acceptable solutions.
Git is a good example though as we can definitely write merge algorithms that get good results in many more cases than git's default but with something like code it's preferable to let the human user decide what is the correct merge solution except trivial cases. Still, a language aware merge algorithm could do a lot better than git in both automatically merging more cases and refusing to merge nonsensical combinations of commits that don't touch the same lines.
Not the parent comment, but I'll respond.
> Your comment shows some ignorance and a complete misunderstanding of the problem domain.
oof, this is a very strong position to take, and one would assume you have a very convincing follow up to back it up.
And unfortunately I don't think you do. CRDTs can definitely be implemented as a last-write implementaiton. This should be obvious for state-based crdts. The problem is that it's a horrible UX because somebody could type a response to something that's out of date, and then just see it dissapear as they get the most recent message.
Resolving "user intent" by choosing how to structure the problem domain (e.g. storing ids for lines, and having custom merging solutions) so that it reflects what the user is trying to do is the main challenge.
I am quite frankly baffled at how arrongant your tone is given how far off the mark you seem to be. Genuinely makes me think that I am missing something given your confidence, but I don't see what point you're making tbh.
>Your comment shows some ignorance and a complete misunderstanding of the problem domain
Imagine how better your comment would be if you ommited the above line, which adds nothing to the correction you try to make, but comes off as stand-offish.
There is next gen web standards initiative namely BRAID that will make web to be more human and machine friendly with a synchronous web of state [1],[2],[3].
"Braid’s goal is to extend HTTP from a state transfer protocol to a state sync protocol, in order to do away with custom sync protocols and make state across the web more interoperable.
Braid puts the power of operational transforms and CRDTs on the web, improving network performance and enabling natively p2p, collaboratively-editable, local-first web applications." [4]
[1] A Synchronous Web of State:
[2] Braid: Synchronization for HTTP (88 comments):
https://news.ycombinator.com/item?id=40480016
[3] Most RESTful APIs aren't really RESTful (564 comments):
https://news.ycombinator.com/item?id=44507076
[4] Braid HTTP:
The author also assumes that users are rational, make no mistakes, and there exists a logical non-conflicting ordering of their updates that makes sense. This is naive, speaking from a perspective of someone who has spent the last 10 years supporting a SaaS mostly for engineers.
Also, when you get a new requirement that needs a modification of the data model, you have to both remodel your CRDTs and make sure you have a migration strategy.
After doing this a few times, your stakeholders are probably fed up with the crawling pace of development, and the whole local-first app is scrapped again and replaced by a more traditional app. Maybe the architect is fired.
Agreed @ not for the faint of heart.
There is at least one alternative "CRDT-free" approach for the less brave among us: https://mattweidner.com/2025/05/21/text-without-crdts.html
Matt Weindner is a really smart guy, but I really disagree with his reasoning with that one. I implemented his fuguemax crdt in just 250 lines of code or so. It’s small, simple and fast. In that blog post he proposes a different approach that might let you save 50 lines of code at the expense of always needing a centralised server.
Seems like a terrible trade to me. Just use a crdt. They’re good.
> Difference from CRDTs
The author has made a CRDT. He denies that his algorithm constitutes a CRDT. It's a straightforward merge, not a "fancy algorithm".
What specific aspect of a CRDT does this solution not satisfy? The C? The R? The D? The T?
I was going to say that that's not a CRDT because it requires a centralized server (the conflict resolution is "order in which the server received the messages", and clients aren't allowed to share updates with each other, they can only get updates from the server). But now I'm looking at definitions of CRDTs and it's not clear to me whether this is supposed to count or not.
Still, every algorithm that's actually labeled a CRDT shares a magical property: if my replica has some changes, and your replica has some changes, our replicas can share their changes with each other and each converge closer to the final state of the document, even if other people have been editing at the same time, and different subsets of their changes have been shared with you or I. That is, you can apply peoples' changes in any order and still get the same result. I don't think it's useful to call anything without that property a CRDT.
The C in CRDT means the order doesn't matter, which means you can just put all the gossiped changes into a big bag of changes and if everyone knows the same changes, they have the same final document, so a simple gossip protocol that just shares unshared data blobs will eventually synchronize the document. If order matters, it's not a CRDT. This one isn't a CRDT because the order matters if two clients insert text at the same position.
There's the additional headaches of a) managing auth in a distributed manner, and b) figuring out how to evolve the data model across all participating clients.
CRDTs are a complicated way to solve a problem that most services don't really have, which is when you want to sync data but don't want to have any one client be the ultimate source of truth.
Yeah I must say, this one (crdt) has been an impossible one to solve for me in practical terms. Every single time we end up with something like this: dataflow has 3 modes/directions: downstream only, upstream only and bi-directional. The majority of systems ends up needing bi-directionality (unless dealing with sensors/iot data) at some point, which means you are forced to deal with conflicts. Which means you end up having to compromise and the simplest compromise for 95% of applications is to say "last one wins", which works near perfect in the real world and it is simpler to maintain and debug. The remaining 5% has a hard constraint where you can either go down an academic rabbit hole with crdt's and come out the other end with some grey hairs, or, you still use your normal data flows but have multistep commits (not in a database sense, but a workflow/saga sense), so you have some supervising object that makes sure both sides agree after x amount of time or revert (think about banks, semi-realtime & distributed, but forced to be consistent).
And for the younger devs: please consider if you need these kinds of sync systems at all (distributed & offline modes), sometimes a simple store-forward of events and/or cache is all you need. If you have some leverage, try to advocate that your application has a hard requirement on an internet connection as often it is cheaper to install fibre redundancies than dealing with the side effects of corrupted or lost data. Might save you from early grey hairs.
ps: the above is written with business/LoB applications in mind, with some offline mobile/desktop apps in the mix, not things like control systems for factories or real time medical equipment.
> Also remember it turns your data model into (...)
I don't this is true at all. A CRDT is not your data model. It is the data structure you use to track and update state. Your data model is a realization of the CRDT at a specific point in time. This means a CRDT instance is owned by a repository/service dedicated to syncing your state, and whenever you want to access anything you query that repository/service to output your data model.
Sometimes problems are hard. Sometimes you create your own problems.
A CRDT requires its own data model that becomes, in a sense, the "main" data model. Because its design and constraints effectively become the design and constraints and requirements on the downstream data snapshot.
CRDT's generally require you to track a lot more stuff in your snapshot model than you would otherwise, in order to create messages that contain enough information to be applied and resolved.
E.g. what was previously an ordered list of items without ID's may now need to become a chain of items each with their own ID, so you can record an insert between two other items rather then just update the list object directly.
So yes, the CRDT is effectively your data model.
We have a local-first app. Our approach?
Just ignore the conflicts. The last change wins.
No, really. In practice for most cases the conflicts are either trivial, or impossible. Trivial conflicts like two people modifying the same note are trivial for users, once you have a simple audit log.
And impossible conflicts are impossible to solve automatically anyway and require business processes around them. Example: two people starting to work on the same task in an offline-enabled task tracker.
>Example: two people starting to work on the same task in an offline-enabled task tracker. Wouldn't this just mean both people are working on it?
I agree that this means humans intervening.. It sounds like there was a comms breakdown. But rather than doing a first-in-best-dressed, it sounds like accurately recording that both users are in fact working on the same thing is the best option since it surfaces that intervention is required (or maybe its intentional, tools insisting that only one person can work on an item at once annoys me). Sounds much better than quietly blowing away one of the user's changes.
In principle, local-first to me means each instance (and the actions each user carries out on their instance) is sacrosanct. Server's job is to collate it, not decide what the Truth is (by first-in-best-dressed or otherwise).
Sure. But then you need to notify users when they come back online that there's a conflict, so they can resolve what to do. You likely need to have a report on the frequency of such occasions for the managers, and so on.
These kinds of conflicts simply can not be solved by CRDTs or any other automated process. The application has to be designed around that.
> In principle, local-first to me means each instance (and the actions each user carries out on their instance) is sacrosanct. Server's job is to collate it, not decide what the Truth is (by first-in-best-dressed or otherwise).
This makes sense only for some applications, though.
And we have not yet started talking about permissions, access control, and other nice fun things.
I doubt you'll ever see this.. Oh well..
I probably should have been explicit in that I'm not arguing in favor of CRDTs, just that the adverse doesn't need to be "send it and accept the collateral".
Draw The Rest Of The Owl energy here, but at least its a nice northern star.
I’ve been experimenting with this, it’s a very interesting problem space!
https://github.com/evelant/synchrotron
Idea is to sync business logic calls instead of state. Let business logic resolve all conflicts client side. Logical clocks give consistent ordering. RLS gives permissions and access control. No dedicated conflict resolution logic necessary but still guarantees semantic consistency and maximally preserves user intentions. That’s the idea at least, requires more thought and hacking.
Wouldn't it be less of an issue if you track the change history, and let users pick a specific historical version? Then it doesn't matter who wins, the end-user can go in and change it. Version control is one of the best parts about Google Docs.
Who is the audience of your app? Is it an internal app for a company, or is it a public facing consumer app?
Public app used by professionals in the field, often with poor or no connectivity. Even having a local read-only copy of data is often helpful for them.
Cool. Yeah in my experience last-write-wins is sufficient for 95% of use cases, and if you add audit trails to help resolve any disputes it gets you to 98%
Just have audit log. No need to try solving every trivial cases. Make something useful.
One solution is to make it so that people see their literal keystrokes in real time. Then they solve the conflict themselves. Like, "stop typing into this text because bob is typing into it".
It's like Ethernet conflict resolution: just access the shared medium and detect collisions in real time.
That's a fair question; we here being under a submission aout local-first apps, and al.
Of course, you know the answer: if you're offline, you're not online. Bob gets to type whatever Bob wants, and until you go online, you don't get to overtype anything.
But the offline enabled property allows exactly that.
Both sides type offline and only sync later. Neither would like their change to just be discarded.
I was responding only to the idea of having no conflict resolution: last edit wins (proposedin a great grandparent comment):
https://news.ycombinator.com/item?id=45341335 "We have a local-first app. Our approach? Just ignore the conflicts. The last change wins."
if you can see the edits being made in real time, keystroke by keystroke, that pretty much solves that problem.
As for offline editing, either don't support it (then you're not local-anything obviously) or you can have some lame workflow like "the document was changed by another user ..."
It's fine if you're talking about a text editor or an Excel table. And it's one of the few cases where CRDTs make sense.
If you have a CRM-like application with a list of users? Not so much.
It sort of depends on the owl though, right? If your CRDT is nothing more than a set of tuples updated on the basis of: these are what my peers have... Is there an abyss of complexity that I'm overlooking here or are simple CRDTs in fact quite simple.
They used to be really popular, back in the ancient times when I was young and full of excitement for all things compute, almost all software was local-first, and.. only :)
But since the entire world economy has turned to purely optimizing for control and profit, there's just no good reason to not screw people over as much and as often as possible, what'll they do ? Switch to someone who won't ? And who would that be ?
> But since the entire world economy has turned to purely optimizing for control and profit, there's just no good reason to not screw people over as much and as often as possible, what'll they do ?
I worked on a somewhat well-known (at the time) product that used on-site hosting.
One of our biggest customer complaints was that we didn’t have a cloud hosted option. Many companies didn’t want to self-host. They’d happily pay a premium to not have to host it.
I think HN underestimates the demand for cloud hosted solutions. Companies don’t want to deal with self-hosted if they can pay someone else a monthly fee to do it.
Yes because its a responsability and generally those are costly. If they don't have real upsides you don't want them. So if you can get the same software utility with none of the management responsability you are very much willing to pay a bit more.
That's a different situation than with offline first software though. With on-prem hosted solutions you'll have someone whose job it is to maintain that hosting and of course they'll want to push that work off to some service provider.
I can't imagine wanting to self-host something like Jira, GitHub, or some wiki product unless there's a very big financial cost difference that more than offsets my time and hardware investment.
Otherwise it seems like I'm just spending time and effort achieving the exact same result.
I work in an org with 8ish FTEs, a handful of student workers, and like 200 volunteers. Almost every service wants $5 or more per user per month, that's $1,140 per month per service. We selfhost open source solutions for everything we can and sometimes have to write something in-house to meet our needs.
That sounds an awful lot like, to you, that is the "very big financial cost difference" I mentioned.
That's short-term thinking. By making your business dependent on cloud solutions you are agreeing to future disruptions from forced changes and price increases that you can't foresee and won't be able to do much about when you learn about them.
That factors into financial incentives, doesn't it?
There are also products that still have licensing costs even when you self host.
I've worked at a large company that self-hosted Atlassian products that were a big part of a full-time team's job.
I've worked at a large company that built virtually all their internal tooling in house.
I've worked at a large company that used cloud-based vendors.
They all had tradeoffs.
One of those companies even forced a migration from cloud based CI to internal CI for cost reasons then stopped us halfway through because they couldn't scale up our hosted CI to keep up fast enough.
I could argue your answer is just as short-term thinking when your critical tools end up costing you more hardware, data center, and salary opex than you planned for (which I have seen).
I think Gitea is superior to Github to organize your repos. I deploy it in the corp I work for too and everyone is very happy with it. It is blazingly fast running on a small virtual machine.
Granted, this is a business that needs on-premise infrastructure anyway because we have inhouse production. So we have a domain controller that can be used for everything auth. We use a combination of that and Entra (shitty name).
I wouldn't want to host Jira because I don't like to work with it. Our wiki is self-hosted as well.
Sadly, we also buy into MS infrastructure and use SharePoint and co. It is soo incredibly slow to work with...
While you can be cloud only, it isn't an environment I would like to work in. Local alternatives are almost maintenance free these days and the costs are so much less for a faster service.
For me it's just a question of where I would want to invest my org's time.
For example: how much time do I want us to spend looking after a task/ticketing system? About zero. How much time do I want my org to invest in DR planning for our self-hosted wiki? About zero.
So unless there's a convincing difference (cost, features, etc), cloud-hosted SaaS would be my choice there.
The answers also probably change a lot based on how the company operates. Would I have been comfortable with a self-hosted wiki when I worked at Facebook and we had a pretty damn good team providing DBs as a service? Yes. Would I have wanted to do the same when I was the sole infra person in my group at another job? No.
I think some time investment is very sensible for any form of decision about infrastructure. Today we have companies complaining about their software dependence, software license costs have heavily increased.
Also, an experienced admin can setup a repository server in a day. This is probably even less time investment than getting offers for solutions. In my opinion the maintenance amount isn't less with SaaS at all as most maintenance work is integrating data.
We do have a self-hosted wiki. We don't even need to think about it if we want to integrate document search or analysis. We own our data completely here and I would argue that data is quite an important chunk of wealth for a company. Some SaaS companies know that as well and they basically take your data hostage. And as a plus, as many things are on a local network, any access to that data is pretty much instant.
To save time on infrastructure decision overall is a mistake in my opinion. You wouldn't do that for your ERP or CRM solutions either.
Have you ever checked the cost of GitHub runners? Quickly offsets self-hosting ones.
Runners? Yes. There are definitely some compute/resource heavy things that are more efficient to self host. Until you run out of capacity and getting more capacity involves something like having go buy more hardware and data center space (which I've had to do, though not for CI reasons specifically).
GPU-heavy tasks were also heavily in favor of buying hardware and self-hosting at the time I was making purchasing decisions at my job.
Not everything falls in that bucket and the examples in my comment don't (GitHub isn't just runners).
Edit: I'll also add a question: what part of "unless there's a very big financial cost difference that more than offsets my time and hardware investment" did you think would not cover "have you checked the cost of GitHub runners?"
I didn't say you were wrong, I was just mentioning that I was absolutely amazed when I discovered how much my startup was spending in GitHub runners.
For sure. Everything metered on time scales up shockingly quickly (cost-wise).
In general, I do prefer fixed costs, so self-hosting resource-intensive things makes sense.
Good luck finding vendor that supports isolation of tenants with sensitive data.
I'm not going to spend time trying to fix problems I don't have.
Obviously if your constraints are different, do what works for you.
> there's just no good reason to not screw people over as much and as often as possible, what'll they do ? Switch to someone who won't ? And who would that be ?
That argument flies in the face of basic economics.
The problem is that the people don't seem to care about being screwed. If they did, it would very profitable to provide the non-screwing, and lots of people would.
The optimist in me believes this is a just a problem of education, understanding, and risk-assessment (ie, the screwing is hidden to them). But even if we grant this, that turns out be a very hard problem to solve.
> That argument flies in the face of basic economics.
The first think any economist will tell you about the foundational rationale of basic economics is it's inability to explain the discrepancy between behavior as predicted by basic economics and behavior as carried out by human beings in the actual real world.
The hard truth that I, a human, do not behave rationally and in my own best interest at all time, or at least in those situations in which the risk or benefit to myself is the greatest, is a hard one to swallow, and many people are innately unable to even consider swallowing that, and as a result, to maintain their own illusion of rationality, they must take the stance that humans are as a rule, rational and therefore will act rationally and in their own best interest, if nothing else, as a preemptive defense against the question "if everyone around you is irrational, then what's the chance that you're the only rational one?"
> Switch to someone who won't? And who would that be?
The issue is that it's not as simple as just "switching" and giving another company your money. How would you migrate your 5-10 years of Confluence pages and Jira tickets if you wanted to switch from Atlassian? You're going to put all of your members through the hassle of switching a booking service/payment process? You know you're being screwed, but the cost to switch is often more than the increased cost. The modern economy is balancing cost increases to your customers with the cost to switch to a competitor.
I think you say 'basic economics' but actually mean 'ideal free market'. Economics is the science of economies, which do not have to be free or market based.
The problem with people's basic understanding of free markets is that it is heavily simplified. We are looking at it from the perspective of 'what if human nature wasn't ever a problem, everyone was always perfectly rational, and everyone had all of the information they needed to make a rational decision'. Those criteria do not and have never existed, which is why the free market fails sometimes at doing some basic things.
Don't get me wrong, it is a great idea and it solves all sorts of problems and we should keep using it -- but don't come to the conclusion that because it all works out in the theory part, then if something in the real world is a certain way then we have to accept that it is efficient and inevitable.
You've made a general argument that shows not all theoretical economic theories about free markets can be trusted. Fair enough. But my claim is much narrower.
It merely relies on the love of money of real people in our current economy, and the premise that there is enough information flow that, if people cared, they would find and pay for products that don't screw their privacy, control, etc. I think both those premises are undeniably true.
> and the premise that there is enough information flow that, if people cared, they would
That's a terrible premise. Why are you assuming that this flow exists and that billions of people are failing individually rather than the simpler one this flow not existing?
One reason: Whenever I've made the case personally to friends/family, people who are smart but not interested in messing around with tech, I am usually met with a giant shoulder shrug. Or perhaps, in a best case scenario, "Yeah that doesn't sound great, but there's no way I'm installing X to deal with it".
We can always say the case hasn't been made well enough, and maybe it hasn't it, but at what point do you just start believing people?
So you are saying that because people are being screwed in the current market that is undeniable proof that people are OK with being screwed by the market?
If I misunderstand you please correct me.
If that is what you contend, then you have no addressed whether or not the market allows them to do otherwise. You take for granted that the market is free and that people are willingly choosing this outcome with perfect knowledge and without any incentives or forces which would compel them to act despite not wanting to be screwed. For instance, if you do not have bargaining power with a company over your contract, you have no choice but to accept it. Can you enter into negotiations before agreeing to a EULA?
There are forces that are not free market forces which constrain actions, there is human tendency to prioritize immediate needs over long term benefits, etc which all play a role.
The fact that:
1. The market exists 2. We have a conception of how the market should work in an ideal 3. People act in a certain way
do not all combine to make it true that 'people prefer it this way'.
That's the point I am making in counter to your assertion.
You are making all these theoretical points... do you doubt that people are demonstrably lazy and willing to give up their privacy and control for free or cheap or convenient stuff? I don't see how this is even a contentious point to make.
You're bringing up all these theoretical counterpoints that either obviously don't apply, or only apply very partially. There are many local only, FOSS options available for every type of software, right now, many free, for people that care about privacy and control in their computing. They generally have tiny market share. If they were made even more convenient, I don't believe the impact would be substantial. By that I mean stuff like brand recognition, what friends are using, and so on would still be more important decision factors than privacy/control features.
This is a people problem, not a "free market not behaving like its theoretical model" problem. Either people don't fully understand the meaning and importance of their privacy, or their revealed preference of not caring that much is just... sadly... true.
The root of the cause is that we allow companies to run mass psychological manipulation campaigns to get people to act against their bests interests. It's not a people problem, it's a corporate propaganda problem.
Right, I guess am focusing more on your using the 'economics' as proof that it is a people problem, because I see it used that way all the time without regard to structures and human elements. Basically people use 'but the market is obviously working so it must just be the way it is'. They see it as the result of a theoretical market structure in which people make purely rational decisions in their best interest on an even playing field with everyone else, instead of a situation which is affected by laws (or lack of them), specific cultural events, and psychology among many other things.
Sorry if I was talking past you instead of with you, but I have to say that I don't think it is fair to call my responses 'theoretical counterpoints'. What I am doing is pointing out that on the face of your claim, you are engaging in what could reasonably be called 'begging the question'. That is, assuming the conclusion in your own argument without actually showing that that conclusion has a logical basis. Saying 'the current situation exists, and because people have mechanisms by which they can affect that situation that means they are in complete control of the situation' is not logically valid unless you can account for those things which they do not have mechanisms to control being irrelevant to the outcome.
Either people are broadly ok with being screwed (my personal experience suggests this) or there is a grand conspiracy to prevent anyone who is not screwing their customers from competing in the market.
Maybe it is the latter, who knows. But what I do know is that the non-screwing options exist, but are often less popular and more expensive (either in price, time, or effort).
And this annoys me to no end. Because _I_ don't want to be screwed. But whether I get screwed or not increasingly depends on how much those around me are willing to get screwed or not.
It's not that people are OK with being screwed over but rather that they have been conditioned into being helpless about it. Big corporations hire psychological experts that know exactly how to manipulate you into thinking you need their products or otherwise act against your own best interests, whether that's through advertisement, peer pressure or whatever else they can come up with.
You yourself admit that while you don't want to be screwed you only have the option of not being screwed if those around you also choose not being screwed yet somehow you conclusion that others are different and must be OK with being screwed. Presumably you also often choose being screwed over being socially ostracized? Do you really make sure that all those around you have options to still interact without without being screwed?
Yes people often technically have options of not getting screwed but those options almost exist in a different world and in order to choose them you have to abandon the one you are living in now. That people cannot afford to do that does not mean that they are OK with being screwed.
I am partially with you on this one.
"Yes people often technically have options of not getting screwed but those options almost exist in a different world and in order to choose them you have to abandon the one you are living in now."
But the question that remains is this: If the true situation is people who'd desperately like not to be screwed, and would pay the same or more for this privilege, but are made helpless by corporate propaganda and market dominance, why do we not see new players rushing in to fill this need? They could take massive amounts of market share.
There are only two explanations I can see:
1. Monopoly forces or similar at work.
2. This is not the actual situation.
Regarding 1, you can make the argument for a network effect/coldstart problem. That seems possible to me as an alternative explanation, and as a way out. Still, in my personal experience, 90% of people just don't care that much, and so are vulnerable to essentially being "bribed" by short-term corporate incentives. The free/privacy-respecting alternatives would have to match this force, and also match the marketing.
> Presumably you also often choose being screwed over being socially ostracised?
No, I only choose being screwed over being homeless, or jobless.
Which didn't use to be a particularly likely scenario but the tides are turning.
I don't care about being socially ostracised for refusing to ever use WhatsApp for example.
We teach children not to cave to peer pressure as if it was a choice they could make, and now you're claiming that caving to peer pressure is not something people choose.
I personally have needed to sync something between 3 and 6 devices over the past 5 years on a daily/weekly basis.
I invite you to figure out how to algorithmically figure this out in a general case without needing Git Merge levels of complexity for data structures far more complicated than lines of code. Peer to peer device merging of arbitrary files for n > 2 conflicts.
The answer - the algorithmically simple and correct answer - is to have a central hoster and the devices operate as clients. And if you have a central hoster, you now gave yourself a job as sysadmin with requisite backup/failover/restore with data management responsibility handling the decade+ case. Or I could hire a central cloud company to manage my tiny slice of sysadmin needs and _not_ have a part time job at home just dealing with file management and multifile merges.
All models that are "I have a laptop and a backup hard disk" are _broken_.
> what'll they do ? Switch to someone who won't ? And who would that be ?
FOSS
> But since the entire world economy has turned to purely optimizing for control and profit
Citation needed.
I believe the lack of popularity is more of an economics problem. There are established business models for SaaS apps or freemium with ads. But, the business model for local-first apps is not as lucrative. Those who like the local-first model value features like: data-sovereignty, end-to-end encryption, offline usage, etc. These properties make existing business models hard-to-impossible to apply.
My current thinking is that the only way we get substantial local-first software is if it's built by a passionate open-source community.
It's crazy that we live in a time when "pay with money and your data" or "pay with your eyeballs" are the only viable options and "pay with your money without your data" can't even be considered.
The problem with local apps is actually a problem with closed-source software. I refuse to rely on closed-source software to access my data because then I am beholden to the vendor of that software to access my data. It’s only slightly better than putting my data in the cloud. What I really want is the source code to that local app so I can guarantee the ability to continue accessing my data forever. This can be done with open source software but very few companies want to sell their product as open source. Some version of source-available may help but you still have the problem of the company discontinuing support so you need some escape hatch on the license in that case and as far as I know nobody has tried.
wouldn't it be enough for the underlying user data to be stored in a well-documented and widely supported format? I don't care if Obsidian, Logseq or similar are open or closed source if my data is just a folder of markdown and jpeg/pngs.
In simple cases maybe but in general how the format is actually interpreted matters more than what some spec says. Markdown is a great example because in practice almost every markdown renderer does things a bit differently.
Would you feel the same way about a closed source local-first app that used sqlite as the underlying database?
That would let you access your data forever, albeit you might still need to write your own scripts to port it to another app.
In theory, open formats would be enough. In practice you still end up depending on peculiarities of the software handling those formats more often than not so I agree that having access to the source code and permission to modify it when the original vendor's interests no longer align with yours is the only solution.
That's because we allow corporations to into misleading that products are free even though you are still paying for them by letting yourself be manipulated into giving third parties your money who then give some of it back to the original service provider. This really needs to be considered a kind of fraud unless the full cost is displayed upfront, not unlike when a vendor charges your card more than the agreed price.
Someone has to prove that there’s a demand for paid local first subscriptions. Open source and tailscale can’t shoulder it all if you want more adoption.
Or split into 2 things:
Most people have a Dropbox, Apple Storage, Google Storage or similar.
A lot of people used to happily pay for desktop software.
It is sort of a combo of those 2 things economically.
Dropbox could sweep up here by being the provider of choice for offline apps. Defining the open protocol and supporting it. adding notifications and some compute.
You then use Dropbox free for 1, 5, 10 offline apps (some may need free some paid) and soon you'll need to upgrade Storage like any iPhone user!
>A lot of people used to happily pay for desktop software.
More or less no one used to "happily" pay. Absent pirating software, they did pay often hundreds of dollars for all sort of software sight unseen (though shareware did provide try before you bought) which often came with minimal updates/upgrades unless they paid for such.
But expectations have largely changed.
Happy as you can be when paying for something!
Making people dependent on a cloud subscription isn't exactly in the spirit of spreading offline programs...
Dependent isn't the intent here. Obviously big corps are incentivised to do that so there is that danger. But ideally it is all based on open standards.
iCloud kind of does this and is the suggested way to store app data files.
It’s not immune to file conflicts across your devices though.
Given the anemic sales of macOS apps vs online subscriptions, I would disagree. I’m sure it’s the same story on windows. Offline only makes sense when your public infrastructure is garbage. Otherwise most people will choose convenience over control.
Adobe and Microsoft might disagree…
MS favors Office 365 online.
Adobe is keen to emphasize that their products are cloud based
We're living in the world of Dubai chocolate and labubu so this tells you everything you need to know about consumer behavior.
Fads and trends have always existed. Literally as long as we've had culture.
What point are you trying to make?
But before it wasn't as easy to create them every few days.
If I had to guess, I would say the GP wants to express that the mass of consumers acts in uninformed silly ways, and with such people local-first has a very low adoption rate, because they usually don't spend a thought about their digital foot/fingerprint or who really owns their data or how they do their personal computing and whether they are independent of anyone else in their personal computing. That there is this huge part of our society, that again and again creates incentives for enshittification.
Is it really a huge part of our society or is it just one that megacorporations amplify as loud as they can because that's how they want people to behave.
That's a good question actually. I don't know for sure. I tend to think, that for many people things like the Internet are mysteriously working and they have no idea how it works, and as a consequence rarely they go further putting up requirements of how it should work for them. They just accept how things online are, status quo of that which is most visible. Ergo complete victims of the network effects in their social bubbles.
You mean influencer behavior. Tiktok/instagram/etc. personalities are very different from how most people behave in the real world. I don't know anyone who has bought into either of these products.
Labubu obsession is a surefire sign of economic depression: https://www.youtube.com/watch?v=l1O6bN2zWSM
The really crazy thing is that everyone just forgot a couple of years ago "Dubai chocolate" meant something a lot more gross.
> The really crazy thing is that everyone just forgot a couple of years ago "Dubai chocolate" meant something a lot more gross.
It's called damage control and yes it's crazy that we blindly allow this kind of society-wide manipulation.
I'm not really sure about this because far too often I see ads for various services/courses/etc that I want to buy, but I don't end up buying because it's a subscription and I just don't have the bandwidth currently to spend time on the thing. I want to buy it and keep it on my shelf until I find the time to get to it, like a book.
And the price they give me from clicking the ad is a limited-time discount so then I'm turned off from ever coming back later and paying the full price i.e. the sucker's price.
Surely this isn't the optimal business model for many of the products that have adopted it.
You're not the average person. You probably also don't have significant credit card debt or rely on buy-now-pay-later for making purchases. Subscriptions are a win-win for the average company and user - users pay less upfront when evaluating the product, and companies can rely on a steady cash flow to continue paying for development and ongoing maintenance costs.
It's not a win for the user. The user is tricked into paying more than a fair price by deceptive business practices. The word for that is fraud, but somehow it's OK because everyone does it.
> paying more than a fair price by deceptive business practices
I see product X is $10/month. I subscribe. I'm not sure where the deception is there? The alternative is likely either the cost of the product is exorbitantly high like $500 for lifetime. Or the developer makes it more affordable but sales peter out and they end up having to go out of business and can't afford to maintain the product after a couple of years. Likely both. And hackernews will complain either way.
The only sustainable model I've seen is lifetime licenses but updates for a single year.
Every time I looked at customer spending graphs at my previous jobs, I realized how my habits have nothing in common with an average consumer. We’re extreme minority in most of the cases.
Yes, I don't think replicated data structures are the problem.
Look at single player video games, cannot get more ideal for local-first. Still you need a launcher and internet connection.
No you don't. There are plenty of games you can buy and go into the wilderness and play just fine offline. Just because game developers WANT you to be online so they can get data doesn't mean you NEED to be online.
That's what confuses me about this whole topic. If you want a local app, make one. Nothing "requires" online if the features don't drive it.
We drove everything online for logistics and financial reasons. Not because the tech requires online connections for everything. it isn't changing because people don't see always-online as a big enough deterrent to change their habits.
Your point is correct, but OP is correct.
There are currently tens of thousands of games that are unplayable due to requiring pinging to a network/patch server which long ago was deprecated.
Forsaking patch requirements, just as many games are no longer playable due to incompatibility/abandoned OS, codebase, gamebreaking bugs.
In both of these scenarios, my "lifetime license" is no longer usable through no action of my own, and breaks the lifetime license agreement. I shouldn't need to be into IT to understand how to keep a game I bought 5 years ago playable.
The solution to this "problem" for user, as offered by the corporate investment firms in control, is to offer rolling subscriptions that "keep your license alive", for some reason. Rather than properly charge for a service at time of purchase.
TLDR: Why move the goal posts further in favor of tech/IT/Videogame Investment firms?
I think this thread is an example of a fascinating class of miscommunication I've observed on HN, but I want to say it out loud to see if I'm understanding it.
Two people meet in an HN thread, and they both dislike the status quo in a particular way (e.g. that copyright is awful, DRMed games suck, whatever). They both want to fight back against the thing that they dislike, but they do it in different ways.
One person finds alternatives to the mainstream and then advertises them and tell people: Look, here's the other way you can do it so you can avoid this terrible mess! That messaging can sometimes come across as downplaying the severity of the problem.
The second person instead wants to raise awareness of how awful the mess is, and so has to emphasize that this is a real problem.
The end result is two people that I think agree, but who appear to disagree because one wants to emphasize the severity of the problem and the other wants to emphasize potential solutions that the individual can take to address it.
Concretely, I think that's what happened here. I think everybody in this thread is pissed that single-player games would have activation and online DRM. Some people like to get around that by buying on marketplaces like GOG or playing open source games, and others want to change the policy that makes this trend possible, which means insisting that it really is a problem.
Sorry for all the meta commentary. If I got it wrong, I'd be interested to understand better!
Welcome to people management. Communication and miscommunication is about 99.999% of it.
Indeed. Most often due to divergence in definitions, scope, prior knowledge, assumptions, time frame, budget, share of burden, objective and/or incentives.
You need a launcher and internet connection in the same way as you "need" to read a 15Mb wall of text to use your iPhone. They need to bully you into it.
I think video games are actually a counter-example: people are still willing to pay for single-player video games and the business model of those doesn't actually rely on Steam working the way it does.
I'm building a file-over-app local-first app call Relay [0] (it makes Obsidian real-time collaborative) and I agree with you.
We have a business model that I think is kind of novel (I am biased) -- we split our service into a "global identity layer"/control plane and "Relay Servers" which are open source and self-hostable. Our Obsidian Plugin is also open source.
So while we have a SaaS, we encourage our users to self-host on private networks (eg. tailscale) so that we are totally unable to see their documents and attachments. We don't require any network connection between the Relay Server and our service.
Similar to tailscale, the global identity layer provides value because people want SSO and straightforward permissions management (which are a pain to self-host), but running the Relay Server is dead simple.
So far we are getting some traction with businesses who want a best-in-class writing experience (Obsidian), google-docs-like collaboration, but local-first. This is of particular interest to companies in AI or AI safety (let's not send our docs to our competitors...), or for compliance/security reasons.
[0] https://relay.md
In some ways this reminds me of what I'm trying to do with connet [0] - give users the choice to completely self-host (all is open source), identity host (e.g. control server as cloud solution, host relays themselves) or even full cloud [1].
This is the primary reason. The heaviest push for SaaS came from Silicon Valley, which wanted a recurring revenue stream model.
> I believe the lack of popularity is more of an economics problem.
It's also a programming complexity problem.
A local-first app has to run on a zillion different configurations of hardware. A cloud-first app only has to run on a single configuration and the thing running on the user hardware is just a view into that singular cloud representation.
This is really not that much of a problem, most hardware differences are either irrelevant or easily abstracted away (if that isn't already done by the OS).
It's not easy, but if the money flowed that way devs would figure stuff out. As is, devs who may have an interest in working on it will simply be rejected.
Agreed. In the pre-internet days you had rigid version releases, there was a time investment in version 1, it released, people bought it and used it, no bugfixes, patches or anything. Then a year or two later, there was version 2, and you could buy that to get the improvements, or just use your old version just fine.
That sort of model collapses where software needs to be constantly updated and maintained lest it rots and dies as the rest of the ecosystem evolves and something dynamically linked changes by a hair. So what's left is either doing that maintenance for free, i.e. FOSS, or charging for it on a monthly basis like SAAS. We've mostly done this bullshit to ourselves in the name of fast updates and security. Maybe it was inevitable.