Soft delete ve hard delete: analitik, destek, GDPR tarzı silme ve sorgu karmaşıklığı için gerçek ödünleri öğrenin; güvenli geri yükleme desenleri de dahil.

Bir silme düğmesi veritabanında iki çok farklı şeyi ifade edebilir.
Hard delete bir satırı tamamen kaldırır. Bundan sonra kayıt yedekler, loglar veya replika yoksa gider. Anlaması basittir, ama kalıcıdır.
Soft delete ise satırı tutar ama genellikle deleted_at veya is_deleted gibi bir alanla silindiğini işaretler. Uygulama işaretli satırları görünmez sayar. İlgili veriyi korursunuz, geçmişi saklarsınız ve bazen kaydı geri getirebilirsiniz.
Bu tercih, beklenenden daha sık günlük işlerinize yansır. Şöyle soruları nasıl cevaplayacağınızı etkiler: “Geçen ay gelir neden düştü?”, “Sildiğim projemi geri getirebilir misiniz?” veya “Bir GDPR silme talebi aldık — gerçekten kişisel veriyi siliyor muyuz?” Ayrıca kullanıcı arayüzünde “silindi”nin ne anlama geldiğini şekillendirir. Kullanıcılar genellikle geri alabileceklerini varsayar; sonra alamadıklarını fark ederler.
Pratik bir kural:
Örnek: bir müşteri bir workspace’i siler, sonra içinde muhasebe için gereken faturalar olduğunu fark eder. Soft delete varsa destek bunları geri getirebilir (uygulamanız güvenli restore yapacak şekilde kurulmuşsa). Hard delete ise genelde yedekler, gecikmeler veya "mümkün değil" açıklamalarıyla sonuçlanır.
Hiçbir yaklaşım her zaman “en iyi” değildir. En az zarar veren seçenek, korumanız gerekene göre değişir: kullanıcı güveni, raporlama doğruluğu veya gizlilik uyumu.
Silme tercihleri analitiklerde hızlıca görünür. Aktif kullanıcı, dönüşüm veya gelir izlemeye başladığınız gün “silinmiş” basit bir durum olmaktan çıkar ve raporlama kararı haline gelir.
Hard delete yaparsanız birçok metrik temiz görünür çünkü kaldırılmış kayıtlar sorgulardan kaybolur. Ancak bağlamı kaybedersiniz: geçmiş abonelikler, geçmiş ekip büyüklüğü veya geçen ayın funnel’ı gibi. Silinmiş bir müşteri, raporları yeniden çalıştırdığınızda tarihsel grafiklerin değişmesine neden olabilir; bu finans ve büyüme toplantıları için ürkütücüdür.
Soft delete yaparsanız geçmişi tutarsınız, ama sayıları yanlışlıkla şişirebilirsiniz. Basit bir “COUNT users” silinenleri de içerebilir. Churn grafiği, bir raporda deleted_at'ı churn olarak sayıp diğerinde yok sayarsanız çift sayım yapabilir. Hatta faturalar kalıp hesap silinmişse gelir de karmaşıklaşabilir.
Genellikle işe yarayan şey tutarlı bir raporlama deseni seçip ona bağlı kalmaktır:
Anahtar nokta dokümantasyondur ki analistler tahmin yürütmesin. "Aktif"nin ne anlama geldiğini, soft-delete kullanıcıların dahil edilip edilmediğini ve bir hesap daha sonra silinirse gelirin nasıl atanacağını yazın.
Somut örnek: bir workspace yanlışlıkla silinip sonra geri getirildiyse. Dashboard silinmişleri filtrelemiyorsa ani bir düşüş ve geri sıçrama gösterir; snapshot'lar sayesinde tarihsel grafik sabit kalırken ürün görünümü silinmiş workspace'leri gizleyebilir.
Silinme ile ilgili destek taleplerinin çoğu aynı şekilde gelir: “Yanlışlıkla sildim” veya “Kayıtım nereye gitti?” Silme stratejiniz, desteğin dakikalar içinde cevap verip veremeyeceğini veya tek dürüst cevabın "Gitti" olup olmayacağını belirler.
Soft delete ile genelde ne olduğunu doğrulayabilir ve geri alabilirsiniz. Hard delete ile destek genellikle yedeklere güvenmek zorunda kalır (varsa) ve bu tek bir öğe için yavaş, eksik veya imkansız olabilir. Bu yüzden tercih sadece veritabanı detayı değildir; ürününüzün bir şeyler ters gittiğinde ne kadar "yardımcı" olabileceğini şekillendirir.
Gerçek destek beklentiniz varsa silme olaylarını açıklayacak birkaç alan ekleyin:
deleted_at (zaman damgası)deleted_by (kullanıcı id'si veya sistem)delete_reason (opsiyonel, kısa metin)deleted_from_ip veya deleted_from_device (opsiyonel)restored_at ve restored_by (geri yüklemeyi destekliyorsanız)Tam bir etkinlik kaydı olmasa bile bu ayrıntılar desteğin şu soruları yanıtlamasını sağlar: kim sildi, ne zaman oldu ve kaza mı otomatik temizlik mi?
Hard delete geçici veriler için uygun olabilir, ama kullanıcıya yönelik kayıtlar için destek yeteneklerini değiştirir.
Destek tek bir kaydı geri getiremezse yedeklerden geri yüklemeye ihtiyaç duyar; bu diğer verileri etkileyebilir. Ayrıca ne olduğunu kanıtlamak zorlaşır ve uzun soruşturmalar olur.
Geri yükleme özellikleri iş yükünü de değiştirir. Kullanıcılar kendileri geri getirebiliyorsa ticket sayısı düşer. Eğer geri yükleme desteğin manuel müdahalesini gerektiriyorsa ticket'lar artabilir ama tekrarlanabilir ve hızlı hale gelir.
"Unutulma hakkı" genelde bir kişinin verilerinin işlenmesini durdurmanızı ve hâlâ kullanılabilir olduğu yerlerden kaldırmanızı gerektirir. Bu her zaman tüm tarihsel agregaları hemen yok etmeniz gerektiği anlamına gelmez, ama artık yasal bir gerekçe yoksa kimliği belirleyici verileri "yalnızca ihtimal" için saklamamanız gerekir.
İşte soft delete vs hard delete ürün tercihinden daha fazlası olur. Soft delete (örneğin deleted_at ayarlamak) genelde kaydı uygulamadan gizler. Veri hâlâ veritabanında, yöneticiler tarafından sorgulanabilir ve genellikle dışa aktarmalarda, arama indekslerinde ve analitik tablolarında mevcuttur. Birçok GDPR silme talebi için bu silme değildir.
Gerçekten purge etmeniz gerekir:
Takımların unuttuğu kısım yedekler ve loglardır. Şifrelenmiş bir yedekten tek bir satırı silmeyebilirsiniz, ama kural koyabilirsiniz: yedekler çabuk süresi dolsun ve geri yüklenen yedekler sisteme alınmadan önce silme olayları tekrar uygulanmalı. Loglar mümkün olduğunca ham kişisel veri saklamamalı ve açık retention limitleri olmalı.
Basit, pratik bir politika iki adımlı silme olabilir:
Platformunuz kaynak kodu veya veri dışa aktarma destekliyorsa, dışa aktarılan dosyaları da veri deposu olarak ele alın: nerede durduğunu, kimlerin erişebildiğini ve ne zaman silineceğini tanımlayın.
Soft delete basit gelir: deleted_at (veya is_deleted) ekle ve satırı gizle. Gizli maliyet şu ki artık veriyi okuduğunuz her yerde bu bayrağı hatırlamanız gerekir. Bir kere unutursanız garip hatalar çıkar: toplamlar silinmiş öğeleri içerir, arama "hayalet" sonuçlar gösterir veya bir kullanıcı gittiğini sandığı bir şeyi görür.
UI/UX kenar durumları hızla ortaya çıkar. Bir ekip "Roadmap" adlı projeyi siler ve sonra yeni bir "Roadmap" oluşturmak ister. Eğer veritabanında isim üzerinde benzersizlik kuralı varsa yeni oluşturma başarısız olabilir çünkü silinmiş satır hâlâ duruyor. Arama da sorun yaratır: listelerde silinmiş öğeleri gizlerken küresel aramada göstermeye devam ederseniz kullanıcılar uygulamanızın bozuk olduğunu düşünür.
Soft delete filtreleri genelde kaçırılır:
Performans genelde ilk başta iyidir, ama ekstra koşul ek işler doğurur. Eğer çoğu satır aktifyse deleted_at IS NULL filtresi ucuzdur. Eğer çok sayıda satır silindiyse veritabanı daha fazla satır atlamak zorunda kalır; doğru indeks yoksa maliyet artar. Basitçe söylemek gerekirse: aktif belgeleri büyük bir çekmecede aramaya benzer, eski belgeler de oradaysa daha çok bakmanız gerekir.
Ayrı bir “Arşiv” alanı kafa karışıklığını azaltabilir. Varsayılan görünümü yalnızca aktif kayıtları gösterecek şekilde yapın ve silinmiş öğeleri açıklayıcı etiketler ve bir zaman penceresiyle ayrı tutun. Hızlı yapılan iç uygulamalarda (örneğin Koder.ai üzerinde oluşturulan iç araçlar) bu ürün kararı çoğu zaman herhangi bir karmaşık sorgu numarasından daha fazla destek taletini önler.
Soft delete tek bir özellik değildir. Bir veri modeli seçeneğidir ve seçiminiz sorgu kurallarını, geri yükleme davranışını ve "silinmiş"in ürününüz için ne anlama geldiğini şekillendirir.
deleted_at artı deleted_byEn yaygın desen nullable bir zaman damgasıdır. Kayıt silindiğinde deleted_at (ve genelde deleted_by kullanıcı id'si) set edilir. "Aktif" kayıtlar deleted_at null olanlardır.
Bu, temiz bir geri yükleme gerektiğinde iyi çalışır: geri yükleme sadece deleted_at ve deleted_by alanlarını temizlemektir. Ayrıca destek için basit bir denetim sinyali sağlar.
Zaman damgası yerine bazı ekipler status alanı kullanır: active, archived, deleted gibi net durumlar. "Arşivlendi" gerçek bir ürün durumuysa (örneğin çoğu ekranda gizli ama faturalamada sayılan) bu yararlıdır.
Maliyeti ise kuralların artmasıdır. Her durumda ne anlama geldiğini arama, bildirimler, dışa aktarmalar ve analitik dahil her yerde tanımlamanız gerekir.
Hassas veya yüksek değerli nesneler için silinmiş satırları ayrı bir tabloya taşıyabilir veya ekleme-yalnız olay günlüğünde kaydedebilirsiniz.
deleted_at, deleted_bystatusBu genelde geri yüklemelerin sıkı kontrol edilmesi gerektiği veya denetim izi isterken silinmiş veriyi günlük sorgularla karıştırmak istemediğiniz durumlarda kullanılır.
Çocuk kayıtlar için de niyetli bir kural olmalı. Bir workspace silinirse projeler, dosyalar ve üyeliklere ne olur?
archived durumuna çevirHer ilişki için bir kural seçin, yazın ve tutarlı kalın. Çoğu "geri yükleme bozuldu" hatası ebeveyn ve çocuk kayıtların farklı silinme anlamları kullanmasından gelir.
Bir geri yükle düğmesi basit görünür ama izinleri gizlice bozabilir, eski veriyi yanlış yere getirebilir veya kullanıcıları "geri yüklendi" beklentisi ile yanıltabilir. Ürününüzün tam olarak ne vaat ettiğini önce yazın.
Geri yüklemeyi öngörülebilir ve denetlenebilir yapmak için küçük, sıkı bir sıra kullanın.
Koder.ai gibi sohbet destekli araçlarda hızlı uygulama geliştiriyorsanız, bu kontrolleri üretilen iş akışının bir parçası yapın ki her ekran ve endpoint aynı kuralları izlesin.
Soft delete ile ilgili en büyük acı, silmenin kendisi değil, kaydın "gitmiş" olduğunu unutmuş olan tüm yerlerdir. Birçok ekip güven için soft delete seçer, sonra silinmiş öğeleri arama sonuçlarında, rozetlerde veya total sayılarda gösterir ve kullanıcılar hızlıca fark eder: panoda "12 proje" yazarken listede 11 görünüyorsa kullanıcılar bunu görür.
İkinci büyük hata erişim kontrolüdür. Bir kullanıcı, ekip veya workspace soft-delete edildiyse giriş yapmamalı, API çağrısı yapmamalı veya bildirim almamalıdır. Bu genelde giriş kontrolü e-posta ile lookup yapıp silinme bayrağını kontrol etmediğinde atlanan bir yerdir.
Destek ticket'ları yaratan yaygın tuzaklar:
Benzersizlik çakışmaları, geri yükleme sırasında özellikle tatsızdır. Birisi eski hesabın email'i ile yeni hesap açtıysa geri yükleme başarısız olur ya da yanlış kimliği üzerine yazma riski doğar. Kurallarınızı önceden belirleyin: purge olana dek tekrar kullanımı engelle, tekrar kullanıma izin ver ama geri yüklemeyi engelle, ya da geri yüklemeyi yeni bir tanımlayıcı altında yap.
Sık görülen bir senaryo: destek görevlisi soft-delete edilmiş bir workspace'i geri yüklüyor. Workspace geri geliyor ama üyeler silinmiş kalıyor ve bir entegrasyon eski kayıtları partner aracına göndermeye başlıyor. Kullanıcı için geri yükleme "yarım çalıştı" ve yeni bir karmaşa yarattı.
Geri yüklemeyi yayına almadan önce şu davranışları açıkça belirleyin:
Bir B2B SaaS ekibinin "Workspace sil" düğmesi var. Cuma günü bir yönetici temizlik yapıp aktif görünmeyen 40 workspace'i siliyor. Pazartesi üç müşteri şikayet ediyor: projeleri yok ve hemen geri yükleme istiyorlar.
Ekip kararın basit olacağını varsayıyordu. Öyle çıkmadı.
İlk problem: destek gerçekten silineni geri getiremez. Eğer workspace satırı hard-delete edilip projeler, dosyalar ve üyelikler cascade ile kaldırıldıysa tek seçenek yedeklerdir. Bu zaman, risk ve müşteri için zor bir cevap demektir.
İkinci problem: analitik bozuluyor. Dashboard "aktif workspace" sayısını deleted_at IS NULL sorgusuyla sayıyor. Yanlış silme grafiklerde ani bir düşüş gösteriyor. Daha kötüsü haftalık raporla karşılaştırıldığında yanlış bir churn sinyali üretiyor. Veri kaybolmamıştı ama yanlış yerden hariç tutulmuştu.
Üçüncü problem: etkilenen kullanıcılardan biri için bir gizlilik talebi geliyor. Kişisel verilerini silmelerini istiyorlar. Sadece soft delete bunu sağlamaz. Ekip kişisel alanları (isim, e-posta, IP logları) temizleyecek bir plana ihtiyaç duyar, ama faturalama toplamları ve fatura numaraları gibi kişilerle ilişkilendirilmeyen agregaları korumak isteyebilir.
Dördüncü problem: herkes soruyor, "Kim delete'e bastı?" Eğer bir iz yoksa destek ne olduğunu açıklayamaz.
Daha güvenli bir desen şöyle olur:
deleted_by, deleted_at ve sebep veya ticket id kaydetBu akış, ekiplerin Koder.ai gibi platformlarda hızlıca kurup sonra silme politikasının aynı derecede tasarlanması gerektiğini fark ettikleri türdendir.
Soft delete vs hard delete seçimi tercih meselesinden çok, bir kayıt “gitmiş” olduktan sonra uygulamanızın hangi garantileri vermesi gerektiğiyle ilgilidir. Bir sorgu yazmadan önce şu soruları sorun:
Kararı akla yatkın tutmanın basit yolu, bir gerçekçi olayı seçip baştan sona yürütmektir. Örneğin: biri Cuma gecesi workspace'i yanlışlıkla siliyor. Pazartesi destek silinme olayını görmeli, güvenli şekilde geri yüklemeli ve geri getirilen verinin silinmesi gereken parçaları canlandırmamalıdır. Eğer Koder.ai gibi bir platform üzerinde uygulama geliştiriyorsanız, bu kuralları erken belirleyip üretilen backend ve UI'nın tek bir politikayı takip etmesini sağlayın.
Ekip ile paylaşılabilecek basit bir politika yazarak yaklaşımınızı seçin. Yazılı değilse zamanla sapar ve kullanıcılar tutarsızlığı hisseder.
Basit kurallarla başlayın:
Sonra birbirine karışmayan iki açık yol oluşturun: "yönetici geri yükleme" yolu (hatalar için) ve "gizlilik purge" yolu (gerçek silme için). Geri yükleme yolu geri döndürülebilir ve loglanabilir olmalı. Purge yolu kalıcı olmalı ve bir kişiyi tanımlayan tüm ilişkili verileri (gerekiyorsa yedekler ve dışa aktarmalar dahil) kaldırmalı veya anonimleştirmelidir.
Silinmiş verinin ürüne geri sızmaması için koruyucular ekleyin. En kolay yol silinmeyi testlerde birinci sınıf durum yapmak: her yeni sorgu, listeleme sayfası, arama, dışa aktarma ve analitik işi için inceleme noktaları ekleyin. İyi bir kural: bir ekran kullanıcıya yönelik veri gösteriyorsa, silinmiş kayıtlar hakkında açık bir karar olmalı (gizle, etiketle veya sadece yönetici göster).
Erken aşamada iseniz her iki akışı da prototipleyin ve şema kilitlenmeden önce deneyin. Koder.ai içinde silme politikasını planlama modunda çizebilir, temel CRUD'u üretebilir ve geri yükleme ile purge senaryolarını hızla deneyip veri modelini ona göre ayarlayabilirsiniz.