Linear beni local-first tavşan deliğine götürdü
(bytemash.net)- Linear kullanınca web uygulaması geliştirme yaklaşımım büyük ölçüde değişti
- Linear, local-first olarak çalışarak anlık tepki ve ağ gecikmesi olmadan etkileşim sağlıyor
- Bu yaklaşımda istemci, bağımsız bir veritabanına sahip ve değişiklikler eşzamansız olarak sunucuyla senkronize edilir
- Fakat dağıtık ortamlarda senkronizasyon, çakışma çözümü, çevrimdışı işleme gibi konuların uygulanması zordur
- Jazz, Electric SQL, Zero gibi local-first ekosistemindeki farklı çözümler ortaya çıkıyor ve geliştirici deneyimi de giderek iyileşiyor
Genel Bakış
Linear adlı proje yönetimi aracını kullanırken, local-first yaklaşımının olağanüstü hız ve kullanıcı deneyiminden büyük ölçüde etkilendim. Geleneksel web uygulamalarında sıkça karşılaşılan ağ gecikmesi, yüklenme durumu, sayfa yenileme gibi durumları neredeyse hiç hissetmemek dikkat çekiciydi. Bu deneyim, local-first paradigmasının teknik prensiplerini ve pratik örneklerini derinlemesine keşfetmeme yol açtı.
Down the Rabbit Hole
Linear’in teknik arka planını incelerken, onların tarayıcının IndexedDB’sini gerçek bir veritabanı gibi kullandığını gördüm. Tüm değişiklikler önce yerelde anında işlenir, ardından GraphQL ve WebSockets ile arka planda senkronizasyon yapılır.
- local-first terimi, UX stratejisi (anlık yanıt) veya verinin yerel olarak tutulup senkronize edilmesi gibi farklı şekillerde yorumlanabilir
- Klasik web uygulamalarında sunucu tek kaynak iken, local-first yapıda her istemcinin kendi veritabanı vardır
- Veritabanının kullanıcıya daha yakın olmasıyla birlikte kullanıcı etkileşimlerinde ağ gecikmesi tamamen ortadan kalkar
The Challenge: This Is Not Trivial
Linear’in yöntemini doğrudan uygulamaya çalışınca karmaşıklığın oldukça yüksek olduğunu gördüm.
- Çevrimdışı/çevrimiçi geçiş yönetimi
- Dağıtık istemciler arasında çakışma çözümü
- Kısmi senkronizasyon (tüm veriyi indirmeden çalışmayı sağlayacak şekilde tasarım)
- Önbellek verisi şema geçişleri
- Dağıtık ortamda güvenlik ve erişim kontrolü
- Bu alanlar ciddi ölçüde mühendislik zamanı ve çaba gerektirir
The Local-First Ecosystem in 2025
2025 itibarıyla local-first ekosisteminde bir dizi güçlü çözüm bulunuyor.
- Electric SQL: Postgres tabanlı bir senkronizasyon motoru
- PowerSync: Kurumsal odaklı çözüm
- Jazz: local-first uygulamaları kolayca kurmayı sağlayan araç
- Replicache: ana akımdaki önceki çözümlerden biri (geliştirme durdurulmuş)
- Zero: Replicache ekibinin yeni yönelimi
- Triplit: TripleStore tabanlı senkronizasyon
- Instant: Geliştirici deneyimine odaklanır
- LiveStore: Gerçek zamanlı senkronizasyon katmanı sağlar
Deep Dive: Jazz
Jazz, "local-first uygulamalarını durum güncellemeleri kadar kolay hale getirir" vaadiyle dikkat çekiyor.
The Mental Model
Jazz, Collaborative Values (CoValues) adlı gerçek zamanlı iş birliği yapısı getirdi.
- Jazz ve Zod ile şema tanımlaması yapılır: Bu tanım basit bir tip değil, otomatik senkronize edilen canlı nesneler gibi çalışır
- Ek bir API rotası, istek/yanıt mantığı veya DTO oluşturmaya gerek olmadan yalnızca nesne durumunu değiştirildiğinde senkronizasyon otomatik gerçekleşir
How Jazz Achieves This
Jazz’in iç mimarisi özetle şu şekilde:
- Tekillik garantisi: Her veriye otomatik olarak benzersiz bir kimlik atanır
- Event sourcing: Değişiklik geçmişi olay olarak saklanır, gerçek zamanlı senkronizasyon verimlirilir
- Uçtan uca şifreleme: Senkronizasyon öncesi istemci tarafında verinin şifrelenmesi. Sunucu yalnızca şifrelenmiş blob’u görür
- Grup tabanlı yetkilendirme tasarımı: Geleneksel ACL yerine grup bazlı yetki modeli, sahipliğin net ayrımı
The Trade-offs
Bu yapı, prototipleme ve hızlı UI geliştirme açısından çok üretken. Ancak bazı doğası gereği dikkat edilmesi gereken noktalar var:
Your Server Is Blind
Uçtan uca şifreleme nedeniyle sunucu, kullanıcı verisini okuyamaz. Sunucu tarafında hangi verilere erişim gerektiği önceden net tanımlanmazsa, izleme veya kötü amaçlı depolamayı önleme gibi denetimlerde kısıtlar oluşur.
Time Travel Is Mandatory
Event sourcing nedeniyle tüm değişiklik geçmişi kalıcı saklanır. Bu nedenle geri al/yeniden yap (Undo/Redo) deneyimi çok kolaydır; ancak GDPR gibi yasal gereksinimler düşünüldüğünde silme işlemi zorlaşabilir.
Storage Goes Brrr
Silme yapılmadığı için depolama tüketimi sürekli artar. Küçük projelerde sorun olmayabilir ama büyük ölçekli SaaS’lerde maliyet hızlıca yükselir.
Local Dev Still Has Quirks
Kimlik doğrulama temelde Passkeys etrafında dönüyor; özel geliştirme veya yerel ortamda HTTPS, sertifika yönetimi ve anahtar taşınması gibi adımlar başlangıçta zahmetli olabilir. Ancak Better Auth entegrasyonu gibi iyileştirmeler planlanıyor.
But Honestly? Still Worth It
Bu kısıtlamalara rağmen, Jazz’in geliştirme deneyimi ve verimliliği son derece etkileyici. Henüz erken aşamada ama, zamanla birçok sorun çözüleceği düşünülüyor.
Exploring: Electric SQL and Zero
Jazz’in aksine, Electric SQL ve Zero daha kademeli bir yaklaşım sunuyor.
- Mevcut Postgres tablolarını doğrudan kullanabilirsiniz
- Electric SQL, bir tablonun bir bölümünü reaktif sorgu (Shape) olarak abone olup UI’ya senkronize edebilir
- Değişiklik (mutasyon) işleme yaklaşımı Jazz’ten farklı ve LiveStore entegrasyonu gibi farklı seçenekler var
- Zero, Electric’e benzer, ancak değişiklik senkronizasyonunu içinde barındırıyor
When Does Local-First Make Sense?
Local-first yaklaşımın uygun olduğu ve zorlayıcı olduğu durumları şöyle özetleyebiliriz
Uygun olduğu durumlar:
- Yaratımsal araçlar (tasarım, yazı, müzik vb.)
- İş birliği özellikli uygulamalar
- Çevrimdışı destek isteyen mobil uygulamalar
- Geliştirici araçları
- Kişisel verimlilik uygulamaları
Zorlu olduğu durumlar:
- Büyük ölçekli sunucu tarafı iş mantığı
- Sıkı denetim (audit) gereksinimleri
- Büyük hacimli analitik sistemler
- Mevcut, derin entegre sistemler
- Sunucunun sıkça istekleri reddettiği sistemler
Looking Forward
Local-first, web geliştirmede bir paradigma değişimi anlamına gelir. Linear, kullanıcı deneyiminde bunu büyük ölçüde kanıtladı. Geliştiricilerin bu yapısal takasları kendi projelerine uygun olup olmadığını değerlendirmesi gerekir.
Jazz ile kişisel bir uygulama geliştirerek gerçek güçlü ve zayıf yönleri ile soyutlamanın sınırlarını deneyimlemeye devam ediyorum. Ekosistem hâlâ erken bir evrede ve araçlar ile kalıplar zamanla olgunlaşıp gelişecektir. Buna rağmen, veriyi yerelde tutmanın avantajları belirgin ve kaybolmayacak gibi görünüyor.
Yeni bir projede bu kısıtları kabul edebiliyorsanız local-first’i denemeye değer. En kötü senaryoda yeni bir mimari desen öğrenirsiniz, en iyi senaryoda ise imkansız gibi hızlı bir kullanıcı deneyimi kurabilirsiniz. 300ms yanıt yarışında bu önemli bir avantaj olur.
1 yorum
Hacker News Yorumu
Zero da Electric ile benzer özellikler sunuyor ve mutasyonları doğrudan destekliyor Zero'nun temel farklılığı sorgu odaklı senkronizasyon Uygulamayı sorgu düzeyinde tasarlayabilirsiniz, neyin senkronize edileceğine dair önceden bir seçim veya ayar yapmanıza gerek kalmadan yalnızca sorguyu çalıştırırsınız; böylece gerektiği kadar veya daha azı senkronize olur İstemcide gereken veri yoksa sorgu otomatik olarak sunucuya geçer ve bu veri senkronize olduktan sonra sonraki sorgularda doğrudan kullanılabilir Bu yöntem oldukça pratik
SSR'yi tercih ediyorum İstemci sadece oturum tokeni, mevcut URL ve DOM durumunu taşımalı Ağ ve sunucular sürekli hızlanıyor Işık hızı sabit ama biz onu hâlâ tamamen kullanamıyoruz Hollow core fiber gibi teknolojilerle internet genelindeki gecikme %30 düşürülebilir RTT 500ms olsa bile SSR ile 16ms içinde render edilen bir sayfa bugün çevrimiçi çoğu web sitesinden çok daha anlık hissettirir Sunucuda HTML yanıtını 60Hz çerçeveden uzun süre render etmek saçma olur Zen5 çekirdeğinde bu süre içinde 30-40MB JSON serileştirmesi yapılabilir Sunucu tarafında bu sadece süslü bir UTF-8 dizisi Bu tür şeyler ms değil μs düzeyinde ölçülmeli İletim gecikmesi yüksek olması, CPU süresini tembelce kullanmanın mazereti değildir SQLite kullanarak milisaniye hapishanesinden çıktım Hostingli SQL servisleri 1ms altı gecikme hedeflerken kısıtlayıcı bir faktördür Tarayıcı standartları da bazı gezinme gecikmesi sorunlarını çözebilir Speculation Rules API referans alın
Ağ ve sunucuların hızlanması SSR için genel bir gerekçe olamaz Belirli bir sunucunun daha fazla hesaplama gücüne sahip olması veya mantığın bölünemediği özel senaryoları öne sürmek anlamına gelir Gerçekte çoğu zaman istemci tarafı render daha hızlıdır Render mantığı veri boyutuna göre çok daha karmaşıksa ve tüm istemci kaynaklarını topladığınızda sunucudan daha fazla olabilir SSR tek seçenek olsaydı bugün Web Assembly'e olan ilgi açıklanamaz olurdu yerel hesaplama üzerine yazıya da bakılabilir Sonuçta hangi yaklaşımın daha iyi olduğu önceden bilinemez; istek anında seçim yapılabilmelidir
Right Tool For The Right Job! Örneğin Google Docs, Sheets gibi iş birliği araçlarını sadece server-side rendering ile halledebilir miyiz? Sadece SSR'a takılı kalınırsa, kullanıcı düzenleme sırasında başka biri içeriği değiştirmiş olabilir Bu araçlar değişiklik etkisi küçük olduğu ve kullanıcıların birlikte çalıştığını anlık olarak gördüğü ve gerçek zamanlı güncellemeler aldığı için iyi çalışır Buna karşılık otel rezervasyonu gibi bir hizmette gerçek zamanlı senkronizasyona gerek yok Öte yandan orta sırada sarsılan senkronizasyon veya yetersiz tasarlanmış kurumsal uygulamalarda, ileride alan ve sistem karmaşıklığı nedeniyle tutarlılığı sağlamak epey zorlaşır
Mevcut SSR uygulamasına aşağıdaki gibi bir kütüphane kolayca ekleyebilsem kullanırım:
Bu gerçek bir happy-pass mühendisliğidir Gerçek dünyada happy pass'te olmayanlar için oldukça hayal kırıklığı olabilir
SSR'nin bugünkü ve gelecekteki ana kullanımı ilk sayfa yüklemesi, özellikle mobildir Sonrasında yalnızca istemcide durum güncellemeleri gerekir, yani her şey daha hızlı olmalı Mühendislik kalitesi düşükse SSR olması fazla bir şey değiştirmez
Ben CRDT tabanlı, local-first mimarisinde açık kaynak bir görev yönetimi yazılımı geliştiriyorum Geliştirme motivasyonum iş birliği gereksiniminin olmaması ve Linear gibi araçların kullanım amacım için çok karmaşık olmasıydı Bu mimarinin avantajları şunlardır:
Jazz bana çok güçlü bir izlenim bıraktı DX'i harika iyi; adeta eşzamanlı ve komut odaklı kod yazıyormuş gibi, geliştirme keyifli Her şey anında hissettiriyor ve çevrimdışı çalışabildiğinden UX de çok iyi En büyük mesele dağıtım ve uzun vadeli sürdürülebilirlik, çünkü veri sürekli büyüyor (çoğu istemcinin hepsini görmesi şart değil, bu yüzden çok düşünmüyorum) En büyük sorun, sık değişen public index için iyi bir çözümün olmaması Teorik olarak public readable list of ids mümkün ama son zamanlarda Anselm ile konuştum, çözüm üzerinde çalıştıklarını söyledi Genel olarak local-first da maliyetsiz değil ama Jazz, geleneksel merkezi sunucu yaklaşımının temel zayıflıklarını çözerse Firestore'un hemen hemen her açıdan yerini alabilir
ElectricSQL ve TanStack DB ikisi de çok iyi, ama web'de local-first'e neden bu kadar odaklanılıyor diye merak ediyorum Mobil taraf için ofline mod nedeniyle local-first'in çok daha gerekli olduğuna inanıyorum Web tarayıcısı kullanıldığında internet çoğunlukla bağlı durumda Üstelik bu local-first teknolojileri teoride iyi görünse de çatışma çözümü olmazsa pratikte kolayca bozulur Mobil uygulamaları local-first yapmakta aldığım ders oldu bunu; bu yüzden CRDT'yi kullanıyorum
Web teknolojisiyle local-first bir uygulama yapmak, native'ye göre çok daha zor Native uygulamada yalnızca kurulum yapmakla offline çalışma varsayılan olur Webde ise AppManifest, ServiceWorker gibi garip yöntemlerle ancak zorla offline desteği eklenir Native'de 30 yıllık C koduyla diske dosya okuyup yazmakla bu iş biter Webde IndexedDB gerçek bir kâbustur, localStorage büyüyünce kullanılamaz, OriginPrivateFileSystem de sınırlı Kullanıcı bir ay içinde bir kez bile siteye girmezse Safari yerel tarayıcı durumunu siler JavaScript veya Emscripten ile wasm build yapsanız bile async web API'lerini dolanarak zorla yönetmek gerekir Apple, 2015'ten beri CoreData + CloudKit ile local+sync için oldukça hazır bir çözüm sunuyor Google tarafında Firebase'nin en yakın alternatif olduğu kanaatindeyim
Ben Replicache ve Zero geliştiricisi olarak web'e neden odaklandığını uzun süre düşündüm Cevabı hâlâ bilmiyorum ama görüşlerimi paylaşayım:
Mobil, web'den çok daha güçlü yerel offline özelliklerine sahip Ama büyük ölçüde verimlilik/iş birliği webde olur ve web daha düşmanca bir ortamdır Sekmeler arası durum senkronizasyonu, depolama silinmesi gibi karmaşık sorunlar vardır Bu yüzden local-first çoğunlukla web odaklı gelişiyor
Senkronizasyon motorlarının web'e önce hitap etmesinin nedeni bu teknolojiler henüz genç ve güncelleme sıklıkları yüksek olduğu için Mobil uygulama güncellemeleri gerçekten acı verici ama web uygulaması güncellemesi çok daha kolay PWA yetenekleri de artık oldukça iyi iOS PWA'ları artık push bildirimi destekliyor; benim için web uygulaması şeklindeki bir mobil uygulama hissi yeterince tatmin edici
Buradaki mesele ‘hangi özelliği kullanabiliyoruz’ değil, inanılmaz hızlı ve tepki veren bir üründe hissettiğiniz ‘zevk’tir Bu yüzden local-first yaklaşımını benimsiyorum
Local first/sync motorlarının iş birliği tarafı yeterince konuşulmamış gibi görünüyor Ben Zero ile bir arkadaşımın iş amaçlı Google Sheets'ini ikame edecek bir proje geliştiriyorum Google Meet'te gerçek zamanlı olarak aynı Sheet'i açıp verileri birlikte işlerken yaşanan bir senaryo var Bu deneyimi eskiden bir web uygulamasıyla düşünemezdim Websocket ile canlı UI çok yaptım ama gelen veriyi doğru konuma koyup yönetmek inanılmaz karmaşık Veri hücreleri yüzlerce ya da binlercesine çıktığında bu kaos hayal edilemeyecek Zero ile sorgu ile veri seçip mutator ile değiştirince herkes aynı anda hemen senkronize olur Sonuçta geliştirme bizzat keyifli bir hale geliyor
Google Docs ilk çıktığında (12 yaşındaydım) gerçek zamanlı senkronizasyon ve iş birliği imlecini gördüğümde, 'Gelecekteki web deneyimi hep bu kadar iş birliğine dayalı olacak' diye düşündüm O dönemde cloud computing popülerdi ve ben yanlış bir inançla, gerçek zamanlı iş birliğini cloud computing'in tanımı sandım Ama sonuçta böyle bir gelecek olmadı 20 yıl geçti ama çoğu web ürünü hala CRUD deneyimi sunuyor (bu site bile öyle) Her seferinde devrim kapıda zannettik; Meteor.js, React vb. umduk ama hâlâ temel davranış şekli olmadılar Bunu gerçekten ana akıma geçmesini hâlâ bekliyorum, bir gün mutlaka olacağına inanıyorum Sadece düşündüğümden daha zor ve her duruma uygulanabilecek kadar uygun araç maliyetine sahip değil
Gerçek zamanlı iş birliğine örnek olarak Discord (temelde 90'ların IRC'sinden pek farklı değil), Zoom (tüm video toplantıları) verilebilir HN gibi bir sitenin CRUD uygulaması olması avantajdır Gerçek zamanlı güncellemeler bazen dağınıklığa sebep oluyor, bu yüzden istemem
Işık hızı gerçekten bir sınırdır Işık dünyanın yarım çevresini geçmek için 56ms alır, gerçek sinyal daha dolambaçlı gider ve dönüşüm ile ek engeller (load balancer, DDOS koruması vb.) yüzünden daha da yavaş olur Latency çoğu durumda eskisine göre bile kötüleşebiliyor
Ben de o erken dönemin o büyüsünü hissettim ama geleceğin hala bir yerde birikmiş olduğu hissi var Yine de gerçek Google Docs tarzı (girdi alanı/gönder düğmesi olmayan) gerçek zamanlı mesajlaşma aracı geliştirmeye devam ediyorum: kraa.io/hackernews
Local-First ve Sync-Engines'in geleceğine inanıyorum local-first framework landscape tablosu gerçekten çok yararlı Kişisel olarak Triplit.dev en iyi olanı oldu ve bunu TanStack DB ile birleştirmek mümkün PowerSync ve NextGraph da keşfetmek istediğim seçenekler Son zamanlarda LocalFirst Conf videolarından NextGraph sunumunu da eğlenceli buluyorum: YouTube video
Bu araçların veritabanı migration desteği nasıl? Uzun vadede sunucusuz bir istemciyi destekleme durumu geldiğinde, çok eski bir şema durumundan roll-forward migration yapmak büyük bir engel olmaz mı? Tek kullanıcı frontend hata ayıklaması bile zorken, şema durumunu da hesaba katarsak karmaşıklık hayalden çok daha fazla olur
Meteor'u çağrıştırıyor
Bu yaklaşımlar geçmişin yöntemlerinin de tekrarını oluşturuyor
Triplit'i mutlaka denemeliyim, InstantDB kullanmış mısınız? Ben de ilgileniyordum ama henüz kullanamadım
Electric'in yaklaşımını uzun süre beğenerek takip ettim Electric, geliştirme karmaşıklığını geliştirciler ve API'lere bıraktığı için tersine sade kalıyor Çift yönlü senkronizasyon çözümleri çoğunlukla sadece basit bir Todo uygulaması seviyesinde iyi işliyor Yetkilendirme, iş mantığı olgunlaşması, migration ve ürün büyümesi devreye girince dayanıklılık konusunda kuşku doğuyor Electric yalnızca okuma senkronizasyonunu view olarak destekliyor; yazma ise mevcut API/rest/rpc üzerinden yapılır, bu yüzden mevcut projelere entegre etmesi kolay
Neden couchdb / pouchdb listede yok diye merak ediyorum Hâlâ oldukça iyi çalışan araçlar