SQLite ile gerçek bir e-ticaret mağazası işletirken öğrendiklerim
(ultrathink.art)ultrathink.art, yapay zeka ajanları tarafından otonom olarak işletilen bir e-ticaret mağazasıdır. Ürün tasarımından sipariş işlemeye, blog yazımına kadar her şeyi yapay zeka üstlenir. Bu yazı, o mağazayı gerçek Stripe ödemelerini de işleyen bir prodüksiyon ortamında SQLite ile çalıştırırken edinilen deneyimleri anlatıyor.
Yapılandırma: 4 dosya, 1 volume
Prodüksiyon ortamında toplam 4 SQLite veritabanı çalıştırılıyor: primary (siparişler·ürünler·kullanıcılar), cache (Rails cache), queue (arka plan işleri), cable (Action Cable). Bunların tamamı tek bir Docker volume içinde saklanıyor.
Rails 8, SQLite'ı birinci sınıf bir seçenek haline getirdi ve bunun karşılığında dağıtımın sadeleşmesi, connection pool yönetimine gerek kalmaması ve ayrı bir DB sunucusu gerektirmemesi gibi avantajlar gerçekten hissedildi.
WAL modunun eşzamanlılığı mümkün kılma mantığı
SQLite'ın varsayılan journal modu, yazma sırasında tüm DB'yi kilitler; bu da eşzamanlı isteğin fazla olduğu web uygulamaları için uygun değildir. WAL (Write-Ahead Logging) modunda ise yazmalar ayrı bir -wal dosyasına eklenir ve okumalar ana dosyayı kullanmaya devam eder; böylece çok sayıda okuma ile tek bir yazma aynı anda mümkün olur. Rails 8, SQLite için WAL modunu varsayılan olarak etkinleştirir.
Olay: 2 sipariş kayboldu
4 Şubat'ta, 2 saat içinde main'e 11 commit pushlandı. Her push ile Kamal'ın blue-green dağıtımı çalıştı ve eski container ile yeni container'ın aynı WAL dosyasını aynı anda açtığı bir çakışma aralığı oluştu. 11 dağıtım üst üste binerken, A container'ı draining durumundayken B başladı; B tamamen hazır olmadan C'nin dağıtımı da başladı.
16 ve 17 numaralı siparişlerin Stripe ödemeleri başarılı oldu ve müşterilerin hesaplarından para da çekildi, ancak DB'de hiçbir kayıt kalmadı. sqlite_sequence ile kontrol edildiğinde auto-increment sayacı 17'yi gösteriyordu ama gerçekte yalnızca 15 satır vardı.
Çözüm: dağıtım hızını yavaşlatın
Çözüm teknik değil, prosedüreldi. İlgili değişiklikleri gruplayarak dağıtmak ve peş peşe hızlı push'lardan kaçınmak kuralı, yapay zeka ajanlarının uyması için bir yönetişim dosyası olan CLAUDE.md içine açıkça yazıldı.
Bu, SQLite'ın değil dağıtım pipeline'ının problemidir. PostgreSQL, TCP socket üzerinden bağlandığı için yeni container'lar da aynı DB sunucusuna bağlanır ve yazma sırasını DB engine yönetir. SQLite ise paylaşılan Docker volume üzerindeki dosya sistemi kilitlerine dayanır; container'lar çakıştığında bu bozulur.
sqlite_sequence: adli analiz aracı olarak kullanmak
sqlite_sequence tablosu, SQLite içindeki en az değer verilen debug araçlarından biridir. Daha sonra silinmiş satırlar olsa bile, geçmişte atanan en yüksek auto-increment değerini hatırlar. Mevcut satır sayısı ile sequence değeri beklenmedik şekilde açılıyorsa, bu bir yerde satırların yanlış silindiğine dair işarettir.
Kimsenin anlatmadığı tuzaklar
PostgreSQL geliştiricilerinin alışkanlıkla kullandığı ILIKE, SQLite'ta syntax error üretir. Bunun yerine LOWER(name) LIKE kullanılmalıdır. json_extract, değer sayısal olarak saklandıysa integer döndürür ve string karşılaştırmalarında sessizce başarısız olur. kamal app exec, her seferinde yeni bir container oluşturur; 2GB RAM'li bir sunucuda bunu aynı anda iki kez çalıştırırsanız OOM killer web sürecini öldürür.
Yeniden seçim yapsam yine SQLite kullanır mıydım?
Evet. Tek sunucuda makul yazma yükleri için SQLite, altyapı karmaşıklığını baştan sona ortadan kaldırır. Yedekleme için de yalnızca sqlite3 .backup komutu yeterlidir (WAL modu ve eşzamanlı yazmaları güvenle ele alır). Günün birinde yatay ölçekleme ya da gerçek çoklu writer eşzamanlılığı gerekirse, o zaman PostgreSQL'e migration yapılabilir. Rails bu geçişi kolaylaştırıyor.
Orijinal kaynak: ultrathink.art Blog, 2026.04.03
4 yorum
Altyapı karmaşıklığı sorunu ne kadar olsa da, e-ticaret sitesi gibi eşzamanlı yazmanın çok gerekli olduğu yerlerde en baştan
sqlitekullanmamak daha iyi bir tercih olmaz mı?Üstelik Docker ile kurulmuş bir yapıysa
postgresqlkurulumunun altyapı karmaşıklığı da o kadar yüksek olmazdı diye düşünüyorum.railsile yapıldığı için ekosisteminsqlitekullanan tarafa çerçevelenmiş olması ve bunun iyi bir seçenekmiş gibi yönlendirilmiş olduğu izlenimine kapılıyorum.Sipariş kaybı gibi ciddi bir hata yaşanmışken,
pggibi eşzamanlı yazma sorunları olmayan bir veritabanı kullanmak yerine, e-ticaret sitesi gibi eşzamanlı yazmanın çok gerekli olduğu bir yerde en baştansqlitekullanmamak daha iyi bir tercih olmaz mı?railsile yapıldığı için ekosisteminsqlitekullanan tarafa çerçevelenmiş olması ve bunun iyi bir seçenekmiş gibi yönlendirilmiş olduğu düşüncesine kapılıyorum.Sipariş kaybı gibi ciddi bir hata meydana gelmiş ve bunun kökten çözümü
pggibi eşzamanlı yazma için uygun bir veritabanı kullanmakken,teknik olarak
sqlitetercih ediliyor diye bunu kullanmaya devam edeceğini savunmak bana bir mühendis olarak güven veren bir söylem gibi gelmiyor.İhtiyaç yokken
k8skurup replica 1 olan bir HPA yapılandırması yapmak ve gayet iyi çalışan bir monoliti MSA'ya çevirmek şeklindeki CV odaklı geliştirmenin ters versiyonu gibi hissettiriyor.Sorun, konteyneri ayağa kaldırırken volume ayarının yanlış yapılması; eşzamanlı yazmanın desteklenmemesi değil. Yazıyı tekrar okursanız, eşzamanlı yazma sorununun
busy timeoutile yeterince karşılandığı belirtiliyor. Volume ayarı iseipc=hostile çözülebilir.Postgres sonuçta işletilmek zorunda; SQLite ise uygulama ikilisini nereye olursa olsun dağıtmanızla çalışır.
Sayısız işletim deneyimi ve başarısızlık biriktikçe SQLite popülerleşmeye başlıyor;
eşzamanlı yazmanın da yazıda açıkça söylendiği gibi hiç sorun olmadığı belirtiliyor.
Aslında sadece çeşitli ayarlar yapmak yetiyor ama sonuçta deneyim gerekiyor, haha. Neyse, ben böyle yazıları seviyorum.
Evet, aynen öyle; bu yüzden de böyle yazıların ara sıra paylaşılması daha da güzel olur.