HN'de tanıtıldı: Triplit - sunucu ve istemcide çalışan açık kaynaklı senkronizasyon veritabanı
(github.com/aspen-cloud)- Triplit, sunucu ile tarayıcı arasında verileri gerçek zamanlı senkronize eden açık kaynaklı bir veritabanıdır; uygulamaya bir Typescript paketi olarak eklenen bir full-stack veritabanı yaklaşımını benimser
- Sunucu depolaması ile istemci sorgu senkronizasyonunu birlikte ele alır; artımlı güncellemeler, özellik düzeyinde çakışma çözümü, yerel önbellekleme, çevrimdışı mod ve otomatik yeniden bağlanmayı destekler
- SQLite, IndexedDB, LevelDB ve Memory gibi takılabilir depolama seçeneklerini destekler; sunucu tarafı kalıcı depolama ve yönetim paneli sunar
- React ve vanilla Javascript içinde sorgu/değişiklik API'leri kullanılabilir; React, Svelte binding'leri, CLI, Console ve Server'dan oluşan bir monorepo olarak sunulur
- Hızlı etkileşim için iyimser güncellemeler, başarısız güncellemeler için geri alma/yeniden deneme, sunucuda zorunlu kılınan okuma-yazma izinleri ve CRDT tabanlı iş birliği özellikleri de sağlar
Triplit'in sundukları
- Triplit, sunucu ile tarayıcı arasında verileri gerçek zamanlı senkronize eden açık kaynaklı bir veritabanıdır
- Uygulamaya Typescript paketi olarak eklenebilen bir senkronize veri deposu sunar
- Verileri sunucuda saklar ve istemcinin sorgularını akıllıca senkronize eder
- Triplit bu yapıyı full-stack veritabanı olarak adlandırır
- Local First topluluğu için yapılmış sunum videosu da vardır: presentation
Temel özellikler
-
Gerçek zamanlı senkronizasyon
- Artımlı güncellemeleri destekler
- Özellik düzeyinde çakışma çözümü sunar
-
Yerel öncelikli kullanım deneyimi
- Tam istemci tarafı veritabanı tabanlı yerel önbellekleme sunar
- İyimser güncellemeler sayesinde tüm etkileşimlerin hızlı hissedilmesini sağlar
- Çevrimdışı mod, otomatik yeniden bağlanma ve tutarlılık garantisini destekler
-
Sunucu depolaması ve operasyon
- Sunucu tarafı kalıcı depolama sunar
- Bir yönetim paneli içerir
- SQLite, IndexedDB, LevelDB ve Memory gibi takılabilir depolama sağlayıcılarını destekler
-
Veri modeli ve API
- Karmaşık veri modelleri için ilişkisel sorguları destekler
- Şema üzerinden veri güvenliği ve Typescript otomatik tamamlama sağlar
- vanilla Javascript ve React içinde sorgu/değişiklik için basit API sunar
-
İş birliği ve güvenlik
- Sunucuda hem okuma hem yazma için izinleri zorunlu kılar
- CRDTs tabanlı iş birliği/çok oyunculu özellikler sunar
- Delta patch kullanarak ağ trafiğini azaltır ve düşük gecikmeyi hedefler
- Başarısız güncellemeler için geri alma ve yeniden denemeleri yönetir
Monorepo yapısı
- TriplitDB: Tarayıcı, Node, Deno, React Native gibi JS ortamlarında çalışacak şekilde tasarlanmış; ağ üzerindeki çoklu yazarı ve tutarlılığı korurken hızlı ve canlı güncellenen sorgular sunan veritabanı
- Client: Yerel ve uzak TriplitDB ile etkileşime giren tarayıcı kütüphanesi
- CLI: Proje iskeleti oluşturma, full-stack geliştirme ortamını çalıştırma, sunucu migration'ları gibi işler için komut satırı aracı
- React:
@triplit/clientiçin React binding'i - Svelte:
@triplit/clientiçin Svelte binding'i - Console: Triplit proje verilerini görüntüleme ve değiştirme, ayrıca şema yönetimi için uygulama
- Server: Triplit istemcileri arasında verileri senkronize eden Node sunucusu
- Server-core: Triplit sunucusu oluşturmak için protokolden bağımsız kütüphane
- Docs: Nextra ile hazırlanmış Triplit dokümantasyonu
- Types: Triplit projelerinin paylaştığı tipler
- UI: shadcn tabanlı paylaşımlı UI bileşenleri
Hızlı başlangıç akışı
- Yeni bir proje
npm create triplit-app@latest my-appile başlar - Mevcut bir projede önce
@triplit/cligeliştirme bağımlılığı olarak kurulur, ardındannpm run triplit initçalıştırılır my-app/triplit/schema.tsiçinde şema tanımlanır- Örnekte
todoskoleksiyonundaid,text,completedalanları tanımlanır completed, varsayılan değerifalseolan bir Boolean alanı olarak ayarlanır
- Örnekte
npm run triplit devile geliştirme amaçlı senkronizasyon sunucusu başlatılır- Geliştirme sunucusu, uygulamanın sunucuyla senkronize olması için gereken ortam değişkenlerini çıktılar
- Vite örneğinde
VITE_TRIPLIT_SERVER_URL=http://localhost:6543 VITE_TRIPLIT_TOKEN=copied-in-from-triplit-dev
- Vite örneğinde
React kullanım örneği ve senkronizasyonu doğrulama
- React örneğinde
TriplitClientveuseQuerykullanılır - İstemci; şema, sunucu URL'si ve token alarak oluşturulur
useQuery(client.query('todos'))iletodossorgu sonuçlarına abone olunur- Checkbox değiştiğinde
client.updateilecompleteddeğeri tersine çevrilir - Uygulama başlatıldıktan sonra başka bir tarayıcı sekmesi açılarak verilerin gerçek zamanlı senkronize olduğu görülebilir
Dokümantasyon ve iletişim kanalları
- Tam başlangıç rehberi: getting started guide
- Daha ayrıntılı eğitim: building a real-time todo app with Triplit, Vite, and React
- Sorular, başlangıç desteği ve yeni özellik önizlemeleri için Discord
- En güncel duyurular Twitter/X üzerinden takip edilebilir
1 yorum
Hacker News görüşleri
Triplit’i https://github.com/thanhnguyen2187/cryptaa projesinde kullandım ve beklendiği gibi çalıştı
Veri modeli, tek bir merkezi DB’yi doğruluğun kaynağı yapmak yerine daha dağıtık/P2P’ye yakın bir tasarımla iyi örtüşüyor, ancak self-hosting ve sorgu dili tarafı biraz zayıf
Sunucu kimlik doğrulama token’ının nasıl oluşturulacağı dokümanda net değildi; ben de CLI’nin
devkomutuyla token oluşturdum. Sistem servisinde token’ın düz metin loglara düşmesi güvenlik açısından iyi değil, ama bunun zaten daha büyük bir erişim yetkisi sorunu varsaydığını düşünüyorumÖzel sorgu DSL’i, SQL’deki
UNIQUE,COUNTgibi ifadelerin gücüne sahip değil; bu yüzden bazı agregasyonları elle yapmak gerekiyorKısa süre önce Evolu’ya baktım https://www.evolu.dev/docs; kapsam ve özellikler açısından benzer görünüyor. Triplit’te
.subscribe()var, Evolu’da yok; Evolu, Kysely tabanlı type-safe SQL kullandığı için sorguları daha tanıdık ve gelişmiş görünüyor. Tarayıcıda Evolu, OPFS üzerinde SQLite kullanırken Triplit sanırım IndexedDB kullanıyorReddit’e yazdığım gönderi: https://www.reddit.com/r/sveltejs/comments/1dndpj8/cryptaa_a...
Sorgu tarafında henüz agregasyon yok ama yol haritasında var; ayrıca artımlı sorgu motoru kullanılırsa çok ilginç bir yöne gidilebileceğini düşünüyorum
Örneğin saat başı güncellenen bir veri panosunda, mevcut sistemlerde (Postgres, MongoDB vb.) sorgunun her seferinde baştan çalıştırılması gerekir; ama Materialize’a benzer bir yaklaşımla yalnızca yeni veriyi işlerseniz çok daha verimli biçimde sürekli güncel kalabilir
Evolu’yu henüz kendim denemedim, ama Discord’da karşılaştırmış biri olabilir: https://triplit.dev/discord
useQueryveya ayrı bir yaklaşımla subscribe desteği sunuyorBöyle harika bir çevrimdışı senkronizasyon protokolü olan bir DB kullanırken, farklı istemci sürümlerini aynı anda yükseltemediğiniz durumlarda şema evriminin nasıl ele alındığını merak ediyorum
Daha önce bir mobil sağlık uygulamasında bu yüzden çok uğraşmıştım
Gerekirse bir süre iki sürüme aynı anda yazan dual-write yapılır
Bu, SQL DB’de uyumluluğu bozan değişiklikleri kesinti olmadan canlıya taşımaya benziyor; ama geçiş zamanı müşteriye bağlı olduğu için bu mantığı daha uzun süre korumak gerekiyor
En güncel sürümü koordine eden bir tablo da önemli; kırıcı bir değişiklik varsa geride kalan istemcinin kullanıcıdan yükseltme yapmasını istemesi gerekir
Ayrıca tüm istemcilerin desteklediği minimum sürüme göre dual-read/write ne kadar süre tutulacağına da karar verilebilir
Triplit, geriye uyumlu olmayan bir değişiklik yaptığınızda uyarı veriyor; bunu dokümanda görebilirsiniz: https://www.triplit.dev/docs/schemas/updating#pushing-the-sc...
Yine de zamanla adı kafa karıştıran çok sayıda alan içeren dağınık şema tanımları doğal olarak oluşabiliyor
Bunu düzeltmeye yönelik bir çözüm henüz yayımlamadık, ama süreci daha az acı verici hale getirecek birkaç şey üzerinde çalışıyoruz. Farklı yaklaşımların arka planı için Cambria dokümanı çok iyi: https://www.inkandswitch.com/cambria/
Sonuçta bir kullanıcı telefonunu iki yıl boyunca çekmecede tutmuş olabilir; bu yüzden her istemci mümkün olan en kısa sürede kendini migrate etse yeterli
Böylece herkesin migration yönetimi için sıfırdan kendi çözümünü kurması gerekmezdi
İstemcinin DB’ye doğrudan yazabilmesinin hangi uygulamalarda makul olduğunu ve backend mantığı olmadan bunun nasıl ayakta kalabildiğini pek anlayamıyorum
Supabase ve Firestore için de aynı soruyu düşünüyorum; sanki bir şeyi kaçırıyorum
Kurumsal tarafta ise durum elbette tersidir; bunu yok sayan tartışmaları görünce insanın canı sıkılıyor
Özellikle teknoloji Twitter’ında belirli bir stack’i ya da çalışma biçimini savunan paylaşımlarda, insanların iş sistemleri hiç kurmadan sadece CRUD uygulamaları yaptıkları o kadar belli oluyor ki; bu yüzden deneyimli geliştiricilerin neden katılmadığını anlayamıyorlar
Ama yoğun backend mantığı olan şeyler için pek uygun görünmüyor
Örneğin Supabase’te satır düzeyi güvenlik diye bir özellik var
İstemci Supabase’e istek gönderebilir, ancak Supabase backend’de ek sorgular çalıştırarak gelen isteğin izinli olup olmadığını değerlendirir
Basit bir örnek olarak, yalnızca
UserIDsütununun değeri isteği yapan kimliği doğrulanmış kullanıcıyla aynıysa o satırın okunmasına, yazılmasına ve güncellenmesine izin verebilirsinizKullanıcı ayarlarını Triplit'te saklıyorlardı ve bu ayarların yöneticiler tarafından yönetilebilmesi gerekiyordu
Kullanıcının uygulama her zaman yerelde çalışıyormuş gibi hissetmesi gerekiyordu ve internet kalitesi de sık sık iyi olmuyordu; ancak kullanıcılar birden fazla cihaz arasında geçiş yaparak kullanıyor ve yöneticilerin diğer kullanıcıların ayarlarını görüp yönetmesi gerekiyordu, bu yüzden senkronizasyon gerekliydi
Genel olarak Triplit'in hem frontend geliştirici deneyimi hem de sunduğu destek harikaydı; issue ya da özellik isteği açıldığında ekip bunları çok hızlı ele alıyordu
Yüksek erişilebilirlikli dağıtım konusunda bir yanıt ortaya çıkarsa, Postgres yerine daha kritik verileri de taşımayı planlıyorlar
Neden AGPL lisansını seçtiklerini merak ediyorum
Local First Discord sunucusu https://localfirstweb.dev/ üzerinden YouTube sunumunu https://www.youtube.com/playlist?list=PLTbD2QA-VMnXFsLbuPGz1... görmüş gibiyim; Show HN'de karşıma çıkması sevindirici
TypeScript kullanmadığım için ana hedef kitlesi olmayabilirim ve web'den farklı olarak bağlantının kararsız olduğu mobil uygulamalarda çoğunlukla local-first kullanıyor, Flutter ve Rust backend kullanıyorum
ElectricSQL ve PowerSync gibi diğer local-first çözümleri istemci ve sunucu veritabanlarını doğrudan senkronize ettiği için istemci/sunucudan daha bağımsız
CRDT tabanlı çözümler de FFI ile istemci ve sunucuda kullanılabiliyor; örneğin automerge Rust olduğu için Flutter tarafında
flutter_rust_bridgeüzerinden FFI ile, web'de WASM ile, backend'de ise Rust olarak kullanılabiliyorTriplit, farklı istemciler arasındaki çatışmasız çözümden ziyade sunucuyu doğruluğun kaynağı yapan daha klasik bir istemci-sunucu senkronizasyonu gibi görünüyor
Neden istemci ve sunucudan daha bağımsız bir veritabanı katmanı yaklaşımı yerine dil düzeyinde bir çözüm seçtiklerini merak ediyorum; ayrıca gelecekte JS tabanlı olmayan diller ve framework'leri desteklemenin zor göründüğünü düşünüyorum
Ayrıca Supabase ile rekabet etmeye çalışıyor gibi görünüyorlar; Supabase de Postgres'in veritabanı düzeyindeki senkronizasyonu ve CRDT üzerinde deneyler yapıyor, bu yüzden https://news.ycombinator.com/item?id=33931971 yakalayıp geçebilir gibi görünüyor
Ancak başlangıçta saf TypeScript'e odaklanmaya karar verdik; pazarın yeterince büyük olduğunu ve PWA'nın geleceğine inandığımızı düşünüyoruz, ayrıca en iyi deneyimi yaratmak için buna odaklanmamız gerektiğine inanıyoruz
Bir gün daha platformdan bağımsız bir şey inşa edeceğimizi düşünüyorum ama bunun zamanı net değil
ElectricSQL ve Supabase ekiplerinin ikisi de son derece iyi ve düşünceli; SQL alanında büyümeye devam edecekler gibi görünüyor, yaklaşımın en temel farkı da burada
Triplit, SQL'den kaçınarak geliştiriciye en iyi deneyimi sunabileceğini düşünüyor ve bu iki felsefenin bir arada var olması için fazlasıyla alan var
LWW ise, istemci tarafındaki bilgi miktarının işlem sayısıyla doğrusal biçimde artıp artmadığını merak ediyorum
Yani kullanıcı veritabanını daha çok değiştirdikçe işlem günlüğü sürekli büyüyor mu, yoksa checkpoint alınıyor mu; kullanıcı günde yüz binlerce hatta milyonlarca işlem yaptığında alan açısından nasıl ölçekleniyor?
Yine de LWW register'ın kendisi geçmiş saklamayı zorunlu kılmıyor; bu, uzun süre çevrimdışı kalan istemcilerin de verimli biçimde senkronize olabilmesini sağlamak için mevcut uygulamanın bir tercihi
Günde bir milyon işleme gerçekten ulaştığımızı söylemek için henüz erken olabilir ama sunucunun otorite olması bir avantaj sağlıyor
Gelecekte Triplit sunucusu her istemcinin son senkronizasyon zaman damgasını takip edebilir ve Postgres'in ölü tuple'ları
VACUUMile temizlemesine benzer şekilde geçmişi kademeli olarak budayabilirTauri'de kullanılabilmesi için Rust binding'leri olsa iyi olurdu
Tauri'nin büyümesi, yakında gelecek mobil cihaz desteği ve son dönemde SQLite'ın popülerliği birleşince, offline-first uygulamalardaki boşluğu kapatabilir ve birçok geliştirme ekibi için varsayılan tercih haline gelebilir
ElectricSQL veritabanı katmanında çalıştığı için dilden bağımsız ve sunucuda Rust kullanıyor; bu nedenle Rust binding'leri hem istemci hem de sunucu tarafında çalışabilir
Birlikte geliştirmek istersen haber vermen iyi olur
Öyleyse Triplit'in doğrudan çalışması gerekir gibi görünüyor
Bir süredir React Native uygulamamda Triplit kullanıyorum ve çok iyi çalışıyor
Kesinlikle tavsiye ederim; benim için gerekli tüm koşulları karşılayan tek local-first DB oldu
Uygun ve mantıklı bir sorgu dili (SQL değil), mükemmel TypeScript desteği, offline destek, React Native desteği var; ayrıca açık kaynak ve self-host edilebilir olması da çok iyi
Mevcut bir PostgreSQL DB ile birlikte kullanmak mümkün değil mi diye merak ediyorum
Henüz kamuya açmaya tam hazır değil ama yakında insanların deneyebilmesini sağlamayı hedefliyoruz
Ben de onu kullanmaya daha çok yaklaşıyorum