Vaka çalışmasıYayında
Gişe
Türkiye’deki küçük tiyatrolar, stand-up kulüpleri ve konser salonları için koltuk haritalı biletleme — hiçbir koltuk iki kez satılmıyor.
- Rol
- Tek başıma — ürün, tasarımın uygulanması, backend, altyapı
- Ne zaman
- 2026
- Backend
- Full-stack
Üye olmadan bir dakikada bilet al: test kartı 4242 4242 4242 4242, ileri bir son kullanma tarihi, CVC 123, 3-D Secure kodu 123456. Demo her gece sıfırlanıyor; kaynak kod gizli.

Kimin için
- Kadıköy ya da Alsancak gibi yerlerde 120–420 kişilik mekânlar; bugün genel bir pazaryeri ya da bir tablo üzerinden satış yapıyor.
- Büyük platformların vermediği üç şeye ihtiyaçları var: kendi koltuk haritaları (localar, tekerlekli sandalye alanları, kısıtlı görüşlü koltuklar, ruhsat kapasitesi), gösteri kapış kapış giderken adil bir satış ve çekmeyen bir bodrumda da çalışan bir kapı uygulaması.
- Koltuğunu telefondan seçmek, 3-D Secure ile ödemek ve sorunsuz çalışan bir QR bilet almak isteyen seyirciler.
Ne yaptım
- Tek başıma, işletilen eksiksiz bir ürün olarak kurdum: Cloudflare Workers üzerinde Hono API, D1 ve SQLite tabanlı iki Durable Object sınıfı — biri her seansın koltuklarının sahibi, diğeri yoğun seanslar için bekleme odasını yönetiyor.
- Onaylanmış bir tasarım prototipinden birebir aktarılan React + Vite seyirci uygulaması: keşfet, canlı koltuk haritası (kaydırma, yakınlaştırma, klavye), yedi dakikalık koltuk tutma, 3-D Secure ödeme, çevrimdışı açılan HMAC imzalı QR e-bilet, PDF ve takvim dosyası, bekleme odası.
- Mekân tarafı: sürümlü bir koltuk haritası editörü (bölümler, eğriler, koridorlar, fiyat fırçası, erişilebilirlik, ruhsat kontrolleri) ve bir satış paneli — ayrıca çevrimdışı kuyruklu, ilk okutmanın kazandığı bir kapı okuyucu PWA’sı.
- iyzico benzeri bir PaymentProvider arkasında ödemeler; bilerek 2–3 mükerrer webhook gönderen yerleşik bir sahte PSP; demoyu her gece sıfırlayan bir cron, hız sınırları, yapılandırılmış loglar, health ve metrikler — ve değişmezi kanıtlayan testler ile yük testi.
Nasıl çalışıyor
1Keşfet
“Bu hafta sahnede ne var?” — hafta şeridi, kategoriler ve şehirler; önce Türkçe, bir tıkla İngilizce.
2Koltuk seç
WebSocket ile canlı koltuk haritası: başkaları alışveriş yaptıkça tutulan ve satılan koltuklar güncelleniyor. Yoğun gösteriler önce bekleme odasından geçiyor.
3Tut ve öde
Koltuklar geri sayımla yedi dakika tutuluyor; kartla ödeme bir 3-D Secure adımından geçiyor.
4Bileti al
Çevrimdışı da açılan cüzdan tarzı bir sayfada HMAC imzalı QR e-bilet, basılabilir PDF, takvim dosyası ve “Biletlerim”.
5Kapıda
Görevli PWA ile okutuyor: yeşil, kırmızı ya da sarı. Okutmalar çevrimdışı kuyruğa giriyor, sonra senkronlanıyor — ilk okutma kazanıyor.
Önemli kararlar
01
Her seansın koltukları tek bir Durable Object’e ait
Yerine: Ortak bir veritabanında satır kilitleri ya da iyimser kontroller.
Neden: Bir seansın her tutma, süre dolumu ve satışı, senkron SQLite transaction’larıyla tek iş parçacıklı tek bir nesnenin içinde çalışıyor; yani bir koltuk yapısı gereği iki kez satılamıyor — iki isteğin paylaşabileceği bir oku-sonra-yaz aralığı yok. Tutmalar alarm’larla düşüyor, canlı güncellemeler uyuyan WebSocket’lerle yayılıyor; D1’deki unique index de ikinci savunma hattı.
02
Idempotent ödemeler; geç gelen ödeme iade edilir, asla çift satılmaz
Yerine: Tarayıcı geri dönüşüne ve ilk gelen webhook’a güvenmek.
Neden: Ödeme adımı bir Idempotency-Key alıyor, sipariş onayı idempotent, webhook’lar olay kimliğine göre tekilleştiriliyor ve her durum geçişi korumalı. 3-D Secure sırasında tutma süresi dolar ve koltuğu başkası alırsa ödeme otomatik iade ediliyor. Sahte PSP her satın almada mükerrer webhook gönderiyor; bu yol sürekli sınanıyor.
03
Yoğun satışların önünde adil bir bekleme odası
Yerine: Koltuk haritasında ilk gelen alır.
Neden: Satış anından önce gelen herkes karıştırılıyor — 11.58’de gelmek 11.59’da geleni geçmiyor — sonra gelenler sırayla giriyor. Bir token bucket dakikadaki girişi ve aynı anda alışveriş yapanları sınırlıyor; giriş, alıcıya bağlı, imzalı ve süreli bir token ve koltuk endpoint’i yoğun bir seansta onsuz isteği reddediyor.
04
Çevrimdışı doğrulanan biletler
Yerine: Her okutmayı sunucuya sormak.
Neden: QR kodları seansa özel bir anahtarla HMAC imzalı; kapı cihazları yalnızca çalıştıkları seansın anahtarını ve bilet listesini indiriyor. Okutmalar yerelde doğrulanıp kuyruğa giriyor ve senkronlanıyor; sunucu en erken okutmayı tutuyor. Bedeli — ele geçirilmiş bir okuyucu yalnızca o seans için bilet üretebilir — belgelendi; yükseltme yolu Ed25519.
Mimari
Koltuk durumu tek bir yerde yaşıyor — seansın Durable Object’inde; D1 ikinci savunma hattı. Buradaki her şey benim.
Sayılar
- çift satılan koltuk — k6, 120 koltuğa 2.000 alıcı
- 0
- ayıklanan mükerrer webhook (96 sipariş için 438 teslimat)
- 342
- test: 14’ü Workers runtime’ında, 26’sı domain unit testi
- 40
- aylık maliyet — Cloudflare’ın ücretsiz planı
- 0 €
Teknolojiler
Backend
- Cloudflare Workers
- Durable Objects
- D1 (SQLite)
- Hono
- TypeScript
- WebSocket hibernation
- Cron Triggers
- Rate Limiting
Frontend
- React
- React Router
- Vite
- PWA · service worker
- jsQR
- qrcode-generator
Ödeme ve güvenlik
- 3-D Secure flow
- Idempotency keys
- HMAC-SHA256
- PBKDF2
Kalite
- Vitest (Workers pool)
- k6
- wrangler dry-run
Galeri

3-D Secure adımlı ödeme — sahte PSP gerçeği gibi davranıyor, mükerrer webhook’lar dahil. 
Telefonda: bekleme odası, koltuk haritası ve e-bilet. 
Koltuk haritası editörü: sürümlü yayın; ruhsat kapasitesi aşılınca engelleniyor. 
Mekânın satış paneli. 
Kapı okuyucu — çevrimdışı çalışıyor, ilk okutma kazanıyor.
Uzun versiyonu ister misin — kod, pipeline, ödünleşimler?
E-posta gönder