logoalt Hacker News

How's Linear so fast? A technical breakdown

310 pointsby howToTestFEyesterday at 7:01 PM159 commentsview on HN

Comments

purple-leafytoday at 2:33 AM

This is cool! Maybe I can incorporate something similar into the browser game and engine I’m developing to remove load states entirely after first load? My thing is fully client side static assets no server.

For context I’ve been obsessed with performance with this game. Prior to this weekend I was struggling to simulate 128 simultaneous players (pathfinding, heavy strategy logic, rendering, all in viewport) and maintaining 120fps on an m1 MacBook Pro - I’d get a very occasional frame drop and my performance was sitting at around 4ms frame times

During the weekend I did very heavy-handed performance sessions and can now simulate 2048 simultaneous players with sub millisecond frame times - that includes all rendering and all logic and includes things like proc gen too.

Further - I’ve been simulating a throttled device with 11.2x cpu throttling (a potato / beet low end mobile devices) and can get stable 60fps at around 256-512 simultaneous players and around 5ms frame times.

My main culprits now are some slight logic issues and startup / boot times which I need to improve on potato devices. I reckon I could take some learnings from linear.

aboodmantoday at 12:39 AM

If you're interested in this kind of experience for your application, check out Zero (https://zero.rocicorp.dev/).

Live demo: https://gigabugs.rocicorp.dev/.

We also list some alternatives here: https://zero.rocicorp.dev/docs/when-to-use#alternatives.

If you're interested in how these things work internally, check out the Replicache design doc: https://doc.replicache.dev/concepts/how-it-works. Replicache was the predecessor to Zero and the core protocol still works the same way.

show 3 replies
ricardobeatyesterday at 9:20 PM

I would always hear about how Linear was fast, but after actually working daily with it, I’ve lost enthusiasm. Search is quite slow, the UI is often clunky (looks good though), “Pulse” is a torrent of noise even at small scale, and I have trouble finding things I need and resort to adding everything to favorites.

Early days’ Trello was the best project tracking experience by far.

simjndyesterday at 7:56 PM

Last year a guy reverse engineered Linear's sync engine and published it on GitHub with a cool explainer.

https://github.com/wzhudev/reverse-linear-sync-engine/blob/m...

show 1 reply
jacobgoldyesterday at 7:46 PM

These kinds of local-first syncing web apps are really interesting and can be really useful, but I think the premise is somewhat wrong.

"A few milliseconds is all it takes to update an issue in Linear. A traditional CRUD app doing the same thing takes about 300ms."

"Any data sent between the client and server costs hundreds of milliseconds."

There’s no solving the problem of a large RTT between an HTTP client and server when it’s due to the speed of light.

But what you can do is locate the backend near users and make sure it’s fast.

For example, it’s very possible to run a web app backend within ~10ms RTT of most users and have the backend render responses within ~10ms too.

In other words, you can absolutely create a traditional CRUD app where doing the same thing takes more like 30ms, not 300ms.

show 6 replies
throwaway7783yesterday at 9:02 PM

Writing an eventually consistent database is hard, it maybe fine for Linear's use cases, but not knowing if my updates made it to the server (aka my team),is problematic. The sync lags have created untold problems in other projects I have worked for, so I always go for a synchronous solution. All the fancy stuff comes out only if it's absolutely needed. I'd rather optimize my server to be blazing fast, and have the user "suffer" network latency.

show 1 reply
HoyaSaxayesterday at 9:06 PM

We use Linear at work. I’m definitely in the minority, but I really struggle with the UX. I also wouldn’t call it fast. Sure the page technically loads reasonably quickly, but half the time I see numbers updating on the page with no visual indicator that data loading is still happening.

show 8 replies
saagarjhayesterday at 7:53 PM

I’ve actually found Linear to be quite slow? There was a week where it would also spin at 100% CPU if I left a tab with it open for a while :(

show 1 reply
Keyframeyesterday at 9:03 PM

This is neat. To be honest, I never considered Linear as "fast". Seemed laggy as most web apps, but in contrast to JIRA it's lightspeed of course. Linear is great though, a real refreshment after JIRA torture.

As for optimistic routes and "fast" - maybe we ought to talk gmail first?

spectraldriftyesterday at 11:50 PM

Linear seems like the kind of app that typically wouldn't need this sort of optimization. I could understand local copy of the DB for indexing, perhaps, but not for normal transactions. This app seems like an example of an app that would typically scale well on the backend - concurrent writes for a single issue would typically be rare, and if sharding is necessary for large customers it should shard quite well.

What about this requires more than a few ms (at most) on the backend, and how does a local copy make that better? It seems like a local copy would create even more inconsistency (and if it doesn't, the backend should be fast too!)

qudatyesterday at 11:36 PM

Preload is the answer to speed. Basically download the clients db on init and then have cache invalidation strategies. I built starfx to basically perform the data sync aspect of this paradigm https://starfx.bower.sh/learn#data-loading-strategy-stale-wh...

cuechanyesterday at 7:46 PM

> A traditional CRUD app doing the same thing takes about 300ms.

300ms seems like a lot. Even if this includes the whole http request+response it still seems unbelievably long.

show 4 replies
hamandcheeseyesterday at 7:54 PM

I worry that optimistic updates is going to become trendy and applied to more software, but without any plan for the "sad path" - failed to sync, sync conflict, etc. Get ready for a whole new era of race conditions and frustration!

show 3 replies
Escapadoyesterday at 8:00 PM

I love using linear and where applicable I try to use optimistic updates in the applications I build too and I think it's a good article that touches on the most important aspects of a performant web app of that caliber.

One thing I would like to point out though is that building a performant sync engine that behaves the way you would like in most cases is a non-trivial thing.

If two users are offline and add, edit, remove issues and come online again, you need to reason about what happens. Sometimes you can get away with Last Writer Wins but what happens if an issue is deleted and then edited. What happens if an item in a list gets re-ordered differently on different clients, what's the final ordering? In which cases can you merge what state and in which do you need to discard something. Do you show a conflict resolution UI? How do you deal with rollbacks. How do you deal with schema drift and updates on items that would be affected by schema drift? Business logic might change between being reconnects. FK constraints can shift. Can you set up your data and the sync engine so that it only syncs the minimum amount of changes and batches them correctly during longer offline sessions so you don't fire 5000 change requests after reconnecting?

I recently had to implement local first + remote sync on some fairly complex dynamic forms and where luckily there is usually only one writer and I can get away with last writer wins and reject if things are too old or if there is schema drift and can just display an error message and roll back. But what I am trying to say is: Whatever can go wrong in an online-first world, can also go wrong in an offline first world but you might get informed of that all at once at a later time - or not at all and your data is not what you think it should be. Some sync engines like zero from rocicorp has opted out of supporting offline writes entirely because of all these problems.

And just to be clear: I love offline first approaches. I yearn for fast performance. And in a lot of cases slapping a sync engine on your app can really be helpful for that if your use case allows it. But it's absolutely crucial to be aware of the pitfalls that come with it.

wbobeirneyesterday at 7:55 PM

I'm glad to see more positive takes on client-side rendering. Unless SEO and crawlability are important for your site, server side rendering is such an overprescribed solution. If I put my tin-foil hat on, I'd say it gets a lot of attention because it's a lot easier to charge people for server time spent in SSR that you just don't have in CSR.

Bottom line is, if your app's content is behind a login screen, just use client side rendering. It is way lower complexity and a way better user experience.

epguiyesterday at 8:24 PM

I’ve never thought of Linear as particularly fast.

show 1 reply
tnelsond4today at 12:12 AM

If it uses indexedb under the hood, indexedb is ridiculously slow on first write but subsequent loads are very fast, if you're loading data you would have to load it via some other method first before putting it in indexedb, in order to make it fast.

Linear is 21mb of minified JavaScript which is an awful lot. I made a dictionary progressive web app recently that just needed read only databases, so I rolled my own simple system complete with zstd compression all in a 38kb wasm module.

syspecyesterday at 7:46 PM

Whole blog post is basically: Make a mutation in the clientside, assume it worked, and save in the background.

show 9 replies
ianberdinyesterday at 7:45 PM

Thanks for the read. It is a bit more complicated than you think. I completely rebuilt this sync engine + orm with relations, lazy loading etc, using Vue + Pinia in https://playcode.io. Google Linear’s videos, they explained in detail their architecture.

Yes, I spent a few months. But it worth it. Every new field, model I need to add, it is so straightforward. I do love frameworks and foundations. They make live easier later by a lot.

show 2 replies
manoDevtoday at 1:02 AM

Good job – but the article seems to introduce new lingo ("sync engine"?) to describe a well known pattern: optimistic user interface.

faangguyindiatoday at 12:49 AM

Well, i also design my apps like this. Basically, my apps are PWA app which sync data in backend to sqlite+go backend.

It's blazingly fast approach.

mattmattersyesterday at 10:57 PM

Linear still only uses j/k for up and down. I've asked over and over for the past 5 years for ctrl+n/ctrl+p up and down and have gotten nonsensical answers from support.

What's crazier is they support this navigation key combo in their command palette but no where else.

The vim line nav is a nice thing in apps, but it's extremely frustrating I can't change it.

herpdyderpyesterday at 9:23 PM

My Linear client gets stuck "syncing" all the time, completely blocking all interaction. I'd rather have loading spinners than getting, essentially, locked out of the whole app for 10 minutes.

pier25yesterday at 8:00 PM

Honestly you can POST to an API to the other side of the world and receive a response in less than 300ms. That's literally the blink of an eye. There are very few use cases where you'd need even lower latency than that while at the same time sacrificing reliability (there's no guaranteed persistent storage in a browser).

wasmpersonyesterday at 8:14 PM

In gamedev, "optimistic updates" are called "client-side prediction," and are a standard part of multiplayer games. IMO it's somewhat risky to apply the technique to web-apps, since each network request typically corresponds to some important operation, and optimistically updating the UI is lying to the user about whether that operation completed successfully.

IMO a good approach is to update the UI immediately but still show some indication that the operation hasn't completed. So in a chat app, for example, add the message to the list of messages, but with contrast reduced slightly to indicate that other people can't see it yet.

show 3 replies
seaalyesterday at 9:20 PM

Pretty nice how they package each article into a skill, wonder how useful they actually are in real world workflows.

https://performance.dev/skills

https://performance.dev/how-is-linear-so-fast-a-technical-br...

zawaidehyesterday at 11:42 PM

It’s really unfortunate that it is built in an apartheid state.

show 1 reply
jwryesterday at 8:11 PM

Linear is the best web app I have ever seen, period. It is also the best bug-tracker I've ever used. I use it, and pay for it (gladly). It's worth it.

I am genuinely impressed with their engineering and design — I aspire to attain these levels, though I lack not only the skills, but also several zeroes in my bank account, I think. Still, it's worth looking at what they do and try to get there!

Big props and kudos to the Linear team. It's an impressive app.

show 2 replies
victor9000yesterday at 9:50 PM

The linear MCP is amazing to work with as it lets me keep all my workflows in the terminal. The ergonomics around search and ticket management are dead simple going through a terminal agent, so I didn't need much more convincing after enabling that configuration.

nilirlyesterday at 8:33 PM

Am I the only that doesn't "get" Linear? Even if speed is the killer feature, isn't an issue tracker a relatively low-frequency application for a dev?

Whenever I use it, I don't feel like I'm doing anything new when compared to all the other issue trackers and Kanban boards I've used before.

show 3 replies
ArcaneMooseyesterday at 9:27 PM

I recently started interacting with JIRA exclusively through AI agents (as a Skill in Cursor) and the difference between Linear and JIRA has immediately evaporated. No UI clunkiness problems if I don't even use it :)

adverblyyesterday at 7:47 PM

Any good resources or wrappers for indexedDB people would recommend? The API seems kinda unapproachable compared to other data stores.

https://github.com/tinyplex/tinybase seems kinda good maybe?

show 2 replies
ozgrakkurtyesterday at 11:52 PM

Focusing on making things actually fast is always better than putting a cache or some hack on it.

Linear IS essentially a crud app so saying crud app does it in 300ms doesn't mean anything in this context imo.

If you have a database stack that is actually fast. And you can use something that is actually fast on the frontend like solidjs. Then you might have something that is actually fast.

But putting more complexity and caches etc. on top of it will leave you chasing issues that cause performance cliffs forever.

Modern hardware is insanely fast, this kind of complexity shouldn't ever be needed even if you consider each individual person is related to thousands of issues. I think most people have a home internet connection that is 100Mbps/s at least and they are on CPU with more than 4 cores and more ram than 8GB. And the frontend is running in a browser like chromium or firefox which is also insanely optimized.

Writing backend in JS, using postgres for database, then also using the clunkiest frameworks for the frontend and then writing something is highperformance is a really high level of delusion

show 1 reply
lampe3yesterday at 7:41 PM

funny how things come back.

I loved meteorjs and its still my fav framework to this day.

Seeing optimistic ui and browser based databases being used this way makes me happy.

I would like to understand how they do the chunking and only updating part of the graph instead all of it.

show 1 reply
jonny_ehyesterday at 9:25 PM

I like it when a spinner represents the truth about the state of the value on the server. I want to know when/if it's been updated.

AG342yesterday at 7:43 PM

I've always wondered how they made the UX so slick - thanks for sharing.

jeffbeeyesterday at 8:26 PM

This is bizarrely laudatory. The app is fast because it is not correct. The user has no way to know if their view is consistent with any other user's view. The user has no way to know if the app silently discarded one of their inputs because of a conflict. Linear developers seem to believe that silent data loss is an acceptable cost for maintaining the illusion of speed.

rsingelyesterday at 10:16 PM

I miss Pivotal Tracker

blauditoreyesterday at 8:01 PM

TL;DR: Background syncing instead of synchronous updates to the cloud.

This is basically a thick client, and comes with according trade-offs. It's interesting and there are some best practices, but I can't help but feeling that either the author is a huge fan or the post is an ad (or "sponsored").

xiaoyu2006yesterday at 7:40 PM

I was expecting a post on how hardware accelerate linear algebra lol

ArtRichardsyesterday at 7:43 PM

They're doing some really cool stuff with Agents too.. automating software pm. it's a huge difference between this and their (unnamed) larger competitors.

greatgibtoday at 12:08 AM

Probably linked to this use of "in-browser" database, but for me, keeping a few linear tabs open for too long, and the memory usage of my web browser skyrocket to abusive levels...

mpalmeryesterday at 9:24 PM

Did we need five thousand words (easily 1/3 of which didn't deal with the main topic) on techniques that aren't exclusive to Linear in the slightest?

joeyguerrayesterday at 9:03 PM

just one thing, this is not the simplest stacks you can find.

ralferooyesterday at 8:17 PM

I've never used linear, but just watching their example video [1] would worry me if I was a user and it's actually doing what they say it's doing.

He creates a task called "Create faster app launch", if we believe the article, it's processing that locally rather than going via the server, and then it's allocated an ID "BRO-5". That the ID is so low suggests it's just adding one to the previous issue ID, and so under heavy load, there are almost certainly going to be conflicts with other users creating tasks and getting identical IDs. Even if the system resolves this by changing one of those IDs, the system shouldn't be presenting the ID to the user until it is guaranteed unique. What if they've already pasted it into a document when the system notices the collision and renumbers it?

[1] https://media.performance.dev/posts/p_gAMR6Z7y49Fp/NZrXs70M_...

EDIT: WTH, there are some seriously bad karma people in this thread - just because I dared to have an opinion that the approach taken by this software might not be the best, my post was downvoted in less than a minute after posting! I'm sure whoever did that carefully considered my argument. If I'm wrong, explain why, don't just downvote my comment. If I'm not wrong, shame on you.

einpoklumyesterday at 10:43 PM

I was expecting a post about how O(n) algorithms can sometimes beat o(n), if you can take advantange of the hardware. Instead I get some mountain of stuff targeting "agents". Bah.

tibbonyesterday at 11:24 PM

Now… why is Jira so painfully slow? Even changing the type of a ticket or moving it takes like 20 clicks and a minute

callamdelaneyyesterday at 8:57 PM

It’s webscale

0xbadcafebeeyesterday at 8:03 PM

> Literally the first lines of code that I wrote was the sync engine, which is very uncommon to what you usually do when you're a startup

He chose the path to a better product rather than the path to a quick buck. That is definitely odd for a silicon valley startup

show 1 reply

🔗 View 8 more comments