世界を動かす技術を、日本語で。

リニアはなぜこんなに速いのか?技術的分析

概要

Linear の高速なUI体験は、 ローカルデータベース非同期同期エンジン など、基礎から積み上げた設計と細かな最適化の積み重ねによるもの。 IndexedDB 活用によるネットワーク依存の排除、 バンドラ刷新 による初回ロード高速化、 サービスワーカー によるキャッシュ戦略が重要。 UI応答性 を最優先し、ネットワーク遅延をユーザーに感じさせない工夫が徹底。 クライアントサイドレンダリング のシンプルな構成を活かし、パフォーマンスと開発体験を両立。 この記事では、Linearの主要な高速化手法と、その設計思想を解説。

Linearの高速UIを支える設計思想

  • Linear は、従来のCRUD型Webアプリと異なり、 UIが直接IndexedDBを参照 するローカルファースト設計

  • ユーザー操作 はまずローカルで即時反映し、その後バックグラウンドでサーバーと同期

  • ネットワーク遅延 によるスピナーやローディング画面を極力排除し、 体感速度 を最大化

  • MobX のようなオブザーバブルストアでインメモリデータを管理し、UIを即座に再描画

  • WebSocket 経由で他クライアントともリアルタイム同期を実現

    • 例:
      • 従来型:APIリクエスト→レスポンス待ち→UI更新→スピナー表示
      • Linear型:ローカル即時更新→非同期でsave()→UIは待たない
  • オプティミスティックUI の思想を徹底し、失敗時のみロールバック

  • ネットワークをボトルネック と捉え、可能な限りリクエスト自体を隠蔽

Linearのスタックとシンプルな構成

  • フロントエンド

    • React + react-dom(UIランタイム)
    • MobX(オブザーバブルグラフ)
    • TypeScript(フルスタック単一言語)
    • Rolldown-Vite(バンドラ、過去はRollupやParcel)
    • ProseMirror + y-prosemirror(リッチテキスト、Yjs CRDTでライブコラボ)
    • Radix UI primitives、Emotion + StyleX、Comlink、idb、graphql-request、Sentry、Inter Variableフォント
  • バックエンド

    • Node.js + TypeScript
    • PostgreSQL(Cloud SQLで300分割)
    • Memorystore Redis(イベントバス・キャッシュ)
    • turbopuffer(類似課題検出用ベクタDB)
    • Kubernetes(GCP上)
    • Cloudflare Workers(エッジプロキシ)
  • その他クライアント

    • Desktop: Electron
    • Mobile: Swift(iOS)、Kotlin(Android)
  • マーケティングサイト

    • Next.js(静的)、styled-components、インラインSVG
  • CSR(クライアントサイドレンダリング) を基本とし、サーバー/クライアントの切り分けの複雑さを排除

  • レガシーブラウザ非対応 による大胆な最適化とシンプルなアーキテクチャ

初回ロード高速化のための工夫

  • バンドラ遍歴 (Parcel→Rollup→Vite→Rolldown)で、 出荷JS/CSSの最小化 を追求
    • モダンブラウザ限定・デッドコード削除・徹底的なコード分割
    • 50%のコード削減、30%の圧縮後サイズ減、初回ロード最大59%短縮、メモリ消費70〜80%減少
  • コード分割 により21MBのJSを数百のチャンクに分割、必要時のみロード
  • modulepreload を活用し、全チャンクを 並列プリロード
    • <script type=module crossorigin ...>と<link rel=modulepreload ...>で依存チャンクを先読み
    • ネットワークのウォーターフォール遅延を解消 し、初回アクセス時に全体をキャッシュ

サービスワーカーによるキャッシュ・オフライン対応

  • サービスワーカー が未訪問ルートやアセット(約1200ファイル)をバックグラウンドでプリキャッシュ
  • 2回目以降のナビゲーション はHTTPキャッシュすら経由せず、即座にサービスワーカーから応答
  • オフライン対応 も実現し、常に高速なUXを維持

まとめ:Linearの高速化から学べること

  • UI応答性 を最優先し、ネットワーク遅延をユーザーに見せない設計

  • ローカルデータベース非同期同期 の組み合わせによる即時性

  • 徹底したコード分割・プリロード・キャッシュ戦略 による初回ロード高速化

  • シンプルなクライアントサイド設計 による開発体験とパフォーマンスの両立

  • オプティミスティックUI最新技術活用 で、ネイティブアプリのような操作感を実現

    • ほとんどのWebアプリでも、 Tanstack QuerySWR などのライブラリで オプティミスティック更新 を組み合わせるだけでも、体感速度は大きく向上可能

Linearの設計思想と手法は、現代Webアプリにおけるパフォーマンス・UX改善の最良のヒント集

Hackerたちの意見

このブログ記事の要点は、クライアント側でミューテーションを作って、うまくいったと仮定して、バックグラウンドで保存するってことだね。

同意するなぁ。人それぞれだけど、自動でUIが更新されるのはあんまり価値を感じないな。自分が見ているビューは、実際のサーバーの状態のスナップショットであってほしい。画面でリクエストが通ったのを見ても、それが実際にサーバーに送信されたかどうかを考えさせられるような混ざった状態は嫌だな。

確かに。これ、ほんと嫌だわ。会議中に何かを更新して結果が見えるけど、他のチームは見えない場合を考えてみて。数百ミリ秒の遅延は関係ないけど、更新が通らなかったらどうなるの?実際にそういうことは起こるしね。

ネイティブアプリだと永続ストレージにアクセスできるからあまり問題にならないけど、ブラウザだと永続性が保証されてないからね。

Linearにはうまくいくけど、タブが開いている状態で、タブが閉じられた場合は、タブを再度開いたときに復旧して、競合解決をすることになる。次のような場合にはうまくいかない:1. ユーザーがボタンをクリックしてタブを閉じて、トランザクションが完了したと思っている場合。トランザクションが完了することが重要。2. 将来的にクライアントが起きたときに競合解決が難しい、または不可能な場合。

これは「最終的な整合性」って呼ばれるやつだと思う。

いわゆるRelayが初めからやってることだね、ハハ。でも、実際にフルに使ってる人が少ないのが悲しい。私のチームは、私が働いてるところでは数少ない一つだよ。重い宣言的ミューテーションディレクティブに楽観的レスポンス(そして楽観的アップデータも、うちのAPIがRelayにあまり対応してないから、イライラするけど)。

こういうローカルファーストの同期ウェブアプリはすごく面白いし、実際に役立つと思うけど、前提がちょっと間違ってる気がする。「Linearでの問題更新は数ミリ秒でできる。従来のCRUDアプリだと同じことに約300ミリ秒かかる。」とか「クライアントとサーバー間で送信されるデータは数百ミリ秒かかる。」って言ってるけど、HTTPクライアントとサーバー間の大きなRTTの問題は光の速さが原因だから解決できないよね。でも、ユーザーの近くにバックエンドを置いて、速くすることはできる。例えば、ほとんどのユーザーに対して約10ミリ秒のRTTでウェブアプリのバックエンドを運用して、バックエンドが約10ミリ秒でレスポンスを返すのは全然可能だよ。つまり、同じことをするのに300ミリ秒じゃなくて、30ミリ秒で済む従来のCRUDアプリを作ることは絶対できる。

クライアントに「仲介バックエンド」を置いて、ローカルストレージに優れたミューテーションを書き込んで、バックグラウンドワーカーがそれをバックエンドに送信するようにすればいい。必要に応じて再試行もね。最悪の場合、バックグラウンドワーカーが失敗した更新についてのメッセージを出して、UIスレッドがそれを受け取って表示することになる。でも、うまくいく流れは超速いままだよ。

ありがとう。300msが速いって言ってる人たちを見て、ちょっとおかしくなりそうだった。30msがずっと目標TTFBだったのに。もしかしたら、Linearはバックエンドで正当な理由で時間がかかるのかもしれないし、フロントエンドからの助けが必要かもしれないけど、それは一般化できないし、JSの一つ一つにはコストがあるからね。

これ、全てのエッジバックエンド間で共有されるデータベースが必要なところでできる?

昨年、ある人がLinearの同期エンジンをリバースエンジニアリングして、クールな説明をつけてGitHubに公開したよ。 https://github.com/wzhudev/reverse-linear-sync-engine/blob/m...

当時話題になったこと:Linearの同期エンジンのリバースエンジニアリング - https://news.ycombinator.com/item?id=44123131 - 2025年5月(コメント33件)

最終的に整合性のあるデータベースを書くのは難しい。Linearのユースケースには合ってるかもしれないけど、更新がサーバー(つまりチーム)に届いたかどうかわからないのは問題だよね。同期の遅延は、他のプロジェクトで無数の問題を引き起こしてきたから、私はいつも同期的な解決策を選ぶ。華やかな機能は本当に必要な時だけ出てくる。サーバーを超高速に最適化して、ユーザーにはネットワークの遅延を「我慢」してもらう方がいいかな。

うん、Linearで不整合があったこともあるけど、JIRAはゴミみたいなもんだから…

これは面白いね。正直言うと、Linearを「速い」とは思ったことがなかった。ほとんどのウェブアプリと同じように遅い感じがしたけど、JIRAと比べればもちろん光の速さだね。Linearは素晴らしいけど、JIRAの苦痛の後の本当のリフレッシュだよ。楽観的なルートや「速さ」については、まずGmailの話をしようか?

仕事でLinearを使ってるよ。少数派だと思うけど、UXにすごく苦労してる。速いとも言えないな。ページは技術的にはそこそこ早く読み込まれるけど、半分の時間はページ上で数字が更新されてるのに、データがまだ読み込まれてるっていう視覚的なインジケーターがないんだよね。

あなたの気持ち、わかるよ。Linearが悪いってわけじゃないけど、良いUXでも速いとも思えないんだよね。

Linearは、結局自分が排除しようとしてたものになっちゃったね—複雑さ。残念ながら、企業が生き残って市場を広げるためには、これが唯一の方法なんだ。

Linearでよくある問題は、同じ内容を何度も書くと上書きされちゃうこと。流れを考えてみて。1. タイプする 2. 一瞬考えるために止まる 3. もう少しタイプする 4. Linearがデータをステップ1に戻しちゃう。これがあるから、Linearでは一文の説明だけで問題を作ることにしてる。これがLinearの得意で速いところ。で、詳細を埋めるためにGitHubに切り替えるんだ。

ほんと最悪だよ。アイテムに期限を追加する方法を同僚に教えてもらわないといけなかった。ナビペインに隠れてるからね。Jiraよりはマシだけど、それはかなり低いハードルだよね。

Linearは「明確さ」の名のもとにUIをクソ化したね。いつもの流れだよ:機能を削除して、見えないテキストと巨大なパディングの小さいアイコンを追加、コントロールを隠す、などなど。例えば、検索フィールドは「ctrl-f」を押さないと表示されない。

Linearが速いって話はいつも聞いてたけど、実際に毎日使ってみて、熱意を失っちゃった。検索はかなり遅いし、UIはしばしばもっさりしてる(見た目はいいけどね)、”Pulse”は小規模でもノイズの洪水だし、必要なものを見つけるのが大変で、結局全部お気に入りに追加しちゃう。初期のTrelloは、プロジェクト管理の体験としては最高だったな。

どうやら「Hacker News」はアカウントを削除させてくれないみたい。じゃあ、これを試してみよう:HACKER NEWSは、カルマが実際に存在すると思ってるバカどもが運営してる。これが本当なら、これを説明してみて?

Linearは今でも上下の操作にj/kしか使えないんだよね。5年間ずっとctrl+n/ctrl+pで上下できるようにお願いしてるのに、サポートからは意味不明な返事しかもらえない。もっとおかしいのは、コマンドパレットではこのナビゲーションキーのコンボが使えるのに、他では全然使えないこと。Vimのラインナビはアプリでは便利なんだけど、これを変更できないのがめっちゃイライラする。

面白いね。次の記事でどうしてそんなに遅いのか説明してくれるのを楽しみにしてるよ。(要約すると、デスクトップアプリに見せかけたウェブアプリってことだね。)