150+ Ülkeye eSIM Sağlama: API Mimarisi ve Ölçeklendirme
Problem: Tek API, 150+ Ülke, Milyonlarca Profil
Rivio’nun backend’ini tasarlamaya başladığımızda, temel zorluk ifade etmesi kolay ama çözmesi güç bir problemdi: Flutter mobil uygulamamızın, her biri farklı teknik entegrasyona, farklı sağlama protokolüne ve farklı faturalandırma modeline sahip operatörler tarafından hizmet verilen 150’den fazla ülkede eSIM profillerini sağlayabilmesini, yönetebilmesini ve ölçümleyebilmesini sağlayan tek bir API sunmak.
Bu yazıda bu problemi çözmek için inşa ettiğimiz mimariyi paylaşıyoruz. Üzerine inşa ettiğimiz GSMA Uzaktan SIM Sağlama standardını, SM-DP+ sunucularıyla nasıl entegre olduğumuzu, profil yaşam döngüsü yönetiminin ölçekte nasıl çalıştığını ve kullandıkça öde eSIM’i bir ürün olarak mümkün kılan API tasarım kalıplarını ele alıyoruz.
GSMA Uzaktan SIM Sağlama (RSP) Mimarisi
eSIM ekosisteminin tamamı, GSMA’nın SGP.22 spesifikasyonunda tanımlanan Uzaktan SIM Sağlama (RSP — Remote SIM Provisioning) adlı bir standart üzerine kuruludur. RSP, bir eSIM profilinin sunucuda hazırlanmasını, internet üzerinden indirilmesini ve cihazın eUICC çipine yüklenmesini — fiziksel erişim olmadan — sağlayan aktörleri, protokolleri ve güvenlik modelini tanımlar.
Tüketici cihazları için RSP’nin temel aktörleri:
- SM-DP+ (Subscription Manager — Data Preparation): eSIM profillerini hazırlayan, depolayan ve teslim eden sunucu. Her operatör kendi SM-DP+ sunucusunu işletir veya bir sağlayıcıdan hizmet alır. Backend’imizin birincil olarak iletişim kurduğu sistem budur.
- SM-DS (Subscription Manager — Discovery Server): Cihazların hangi SM-DP+ sunucusunun kendileri için bir profil barındırdığını keşfetmesine yardımcı olan isteğe bağlı bir kayıt servisi. Bir profil sağladığımızda, kullanıcının cihazının QR kod taramadan profili bulup indirebilmesi için bunu SM-DS’ye kaydedebiliriz.
- LPA (Local Profile Assistant): Son kullanıcı cihazındaki (iOS ve Android’e entegre) yazılım; profillerin eUICC üzerine indirilmesini ve kurulmasını yönetir.
- eUICC: Cihaz üzerindeki, kurcalamaya dayanıklı güvenli eleman çipi; eSIM profillerini saklar ve çalıştırır.
Rivio’nun mimarisinde backend’imiz, kullanıcının mobil uygulaması ile birden fazla SM-DP+ sunucusu arasında bir aracı olarak görev yapar. Uygulama hiçbir zaman doğrudan bir SM-DP+ ile iletişim kurmaz — tüm sağlama akışları, operatör seçimi, profil hazırlama, aktivasyon kodu üretimi ve yaşam döngüsü takibini yöneten API’miz üzerinden geçer.
SM-DP+ Entegrasyonu: Sağlamanın Kalbi
SM-DP+ ile entegrasyon, SGP.22’de tanımlanan sunucudan sunucuya protokol olan ES2+ arayüzünü uygulamak anlamına gelir. Bu basit bir REST API değildir. ES2+, karşılıklı TLS (mTLS) ile HTTPS kullanır ve yük formatı, profil sipariş etme, onaylama ve yayınlama için zorunlu alanlara sahip belirli bir JSON yapısını takip eder.
Backend’imiz açısından tipik sağlama akışı:
- Profil Sipariş Et — SM-DP+ sunucusuna ICCID’yi (veya otomatik atama talebini), bilinen hedef EID’yi ve profil tipini belirten bir
DownloadOrderisteği göndeririz. SM-DP+ isteği kabul eder ve profil hazırlığına başlar. - Siparişi Onayla — SM-DP+ profili hazırladığında siparişi onaylarız. Bu noktada SM-DP+, bir aktivasyon kodu (SM-DP+ adresi ve eşleşme kimliği kombinasyonu) üretir.
- Profili Yayınla — Profili indirmeye hazır hale getirmek için
ReleaseProfileçağrısı yaparız. SM-DP+ artık hedef cihazın LPA’sından gelen bağlantıları kabul eder. - SM-DS’ye Bildir — İsteğe bağlı olarak, cihazın profili QR kod taramak yerine push bildirim aracılığıyla keşfedebilmesi için profili SM-DS’ye kaydederiz.
Bu adımların her biri bağımsız olarak başarısız olabilir. SM-DP+ profil envanteri tükenmişse siparişi reddedebilir. Onaylama yük altında zaman aşımına uğrayabilir. Sağladığımız EID ile cihazın indirme sırasında sunduğu EID arasında uyumsuzluk varsa yayınlama başarısız olabilir. Her hata modunu açıkça ele alırız; adım başına farklı yeniden deneme ve eskalasyon stratejileri uygularız.
Profil Yaşam Döngüsü Yönetimi
Bir eSIM profili statik bir nesne değildir. Sistemimizin takip etmesi gereken bir yaşam döngüsüne sahiptir:
Hazırlama — Operatörün SM-DP+ sunucusu profili oluşturur. Bunu sipariş yanıtında dönen ICCID üzerinden takip ederiz.
İndirme — Kullanıcının cihazı SM-DP+ ile iletişim kurar ve profili indirir. SM-DP+‘dan bir ProfileDownloaded geri çağrımı alırız.
Kurulum — LPA, profili eUICC üzerine kurar. Bir ProfileInstalled bildirimi alırız.
Etkinleştirme — Profil aktive edilir ve cihaz operatörün ağına kayıt olur. Bunu operatörden gelen RADIUS Access-Accept mesajları aracılığıyla tespit ederiz.
Devre Dışı Bırakma — Kullanıcı (veya sistemimiz) profili devre dışı bırakır. Cihaz operatör ağından bağlantısını keser.
Silme — Profil eUICC’den kaldırılarak bir yuva serbest bırakılır. Kullanıcı hesabından bir ülkeyi açıkça kaldırdığında ES2+ üzerinden bir DeleteProfile isteği tetikleriz.
Her profil için PostgreSQL’de bir durum makinesi tutarız ve her geçiş yalnızca ekleme yapılabilen bir denetim tablosuna kaydedilir. Bu bize tam izlenebilirlik sağlar — “Bu kullanıcının Japonya profili 3 Nisan’da 14:22 UTC’de neden etkinleştirilemedi?” gibi soruları, durum geçişlerini ve SM-DP+ geri çağrım yüklerini yeniden oynatarak yanıtlayabiliriz.
Çoklu Operatör Yönlendirme
Rivio 150’den fazla ülkeyi kapsar, ancak hiçbir tek operatör hepsini kapsamaz. Operatör matrisimiz, her ülkeyi ağ kalitesi, maliyet ve geçmiş güvenilirliğe göre sıralanmış bir veya daha fazla operatöre eşler.
Flutter uygulaması belirli bir ülke için profil talep ettiğinde, yönlendirme katmanımız:
- Ülkeyi operatör matrisinde arar
- En yüksek sıralı mevcut operatörü seçer
- O operatörün SM-DP+ profil envanterini kontrol eder (envanter sayılarını 5 dakikalık TTL ile önbelleğe alırız)
- Envanter tükenmişse veya birincil operatörün SM-DP+ sunucusu sorunluysa bir sonraki operatöre geçer
Bu yönlendirme kullanıcıya görünmezdir. “Japonya’da veri” talep ederler ve çalışan bir profil alırlar. Arkasındaki operatör, şartları yeniden müzakere ettiysek veya daha iyi kapsama alanına sahip yeni bir operatör ağımıza katıldıysa geçen aydan farklı olabilir.
Yönlendirme kararlarını her sağlama olayıyla birlikte saklarız; bu da operatör puanlama algoritmamızı besler. Bir operatörün profilleri belirli bir ülkede sürekli olarak etkinleştirilemiyorsa, algoritma o operatörü o ülke için kademeli olarak geri plana atar.
Kullandıkça Öde: Bakiye ve Kullanım Ölçümleme
Rivio’da en zor backend problemi sağlama değil — ölçümlemedir. Kullandıkça öde, kullanıcıları sabit bir veri paketi için değil, tüketilen gerçek megabayt başına ücretlendirdiğimiz anlamına gelir. Bu, farklı raporlama yeteneklerine sahip düzinelerce operatör arasında neredeyse gerçek zamanlı kullanım takibi gerektirir.
CDR alımı: Operatörler bize Çağrı Detay Kayıtlarını (CDR) SFTP aktarımları, gerçek zamanlı API beslemeleri veya RADIUS muhasebe mesajları aracılığıyla gönderir. Her formatı farklıdır. Derecelendirme motoruna ulaşmadan önce her şeyi alım hattımızda kanonik bir CDR şemasına normalize ederiz.
Derecelendirme motoru: Normalize edilmiş bir CDR alır, uygulanacak tarifeyi (ülkeye, operatöre ve bazen günün saatine göre değişir) arar ve kullanıcının cüzdan para biriminde maliyeti hesaplar. Derecelendirilmiş olay deftere yazılır.
Bakiye uygulaması: Gerçek zamanlı RADIUS güncellemeleri bir kullanıcının bakiyesinin sıfıra yaklaştığını gösteriyorsa, operatörün AAA sunucusuna bir Disconnect-Request göndeririz. Oturum sonlandırılır ve kullanıcı bakiye yüklemesi için yönlendirilir.
Uzlaştırma: Haftalık olarak, dahili CDR kaynaklı toplamlarımızı operatörün faturasıyla uzlaştırırız. Tutarsızlıklar olur — saat dilimi uyumsuzlukları, mükerrer CDR’ler, geç gelen kayıtlar. Uzlaştırma hattımız %0,5’in üzerindeki her farkı manuel inceleme için işaretler.
API Tasarım Kalıpları
Flutter uygulamasına hizmet eden API, birkaç bilinçli tasarım tercihi izler:
Tüm yazma işlemlerinde idempotency anahtarları. Her POST isteği (profil sağla, bakiye yükle, profil durumu değiştir) bir Idempotency-Key başlığı gerektirir. Anahtarı ve yanıtı 24 saat saklarız. İstemci yeniden denerse (örneğin, ağ zaman aşımından sonra), işlemi tekrar yürütmek yerine saklanan yanıtı döndürürüz. Bu, çifte sağlamayı önler — bize gerçek para maliyeti olacak bir senaryo.
Webhook tabanlı durum güncellemeleri. Uygulama, sağlama durumu için sürekli sorgu yapmaz. Bir profil durum geçişi yaptığında (indirildi, kuruldu, etkinleştirildi), backend’imiz Firebase Cloud Messaging aracılığıyla uygulamaya bir olay iletir; uygulama güncellenmiş profil nesnesini çeker. Bu, API’mizi yormadan uygulamayı duyarlı tutar.
İşlem sınıfına göre hız sınırlama. Sağlama uç noktaları, okuma uç noktalarından (60 istek/dakika) daha agresif şekilde hız sınırlanmıştır (kullanıcı başına dakikada 5 istek). Sağlama, pahalı ve yavaş olan aşağı akış SM-DP+ çağrılarını içerir; hem kendi sistemimizi hem de operatör ortaklarımızı ani trafik patlamalarından koruruz.
Zorunlu minimum ile sürümlü API. Uygulama bir X-API-Version başlığı gönderir. Mevcut ve önceki ana sürümü eş zamanlı destekleriz. Uygulama desteklenen minimumun altında bir sürüm gönderirse, API uygulama mağazasına bağlantı içeren bir 426 Upgrade Required yanıtı döndürür. Bu, eski istemcilerin kullanımdan kaldırılmış sağlama akışlarına ulaşmasını engeller.
Hata Yönetimi ve Yeniden Deneme Stratejisi
SM-DP+ sunucuları her zaman hızlı veya güvenilir değildir. Yeniden deneme stratejimiz katmanlıdır:
- Geçici hatalar (5xx, zaman aşımı): Üstel geri çekilme, 2 saniye başlangıç, 5 dakika üst sınır, en fazla 8 deneme. Eşzamanlı istekler arasında yığılma etkisini önlemek için jitter uygulanır.
- İstemci hataları (4xx): Yeniden deneme yok. Hata kaydedilir, kullanıcıya yönelik bir mesaja eşlenir ve hemen döndürülür. Yaygın nedenler: EID uyumsuzluğu (kullanıcı QR kodu yanlış cihazda taradı), profil bulunamadı (ICCID süresi dolmuş).
- Kısmi başarı:
DownloadOrderbaşarılı olupConfirmOrderbaşarısız olursa, siparişi yeniden denemeyiz — yalnızca onaylamayı yeniden deneriz. Her yaşam döngüsü adımının kendi yeniden deneme bağlamı vardır.
Tüm hatalar Grafana panolarımızda görünür: operatör başına, ülke başına, saat başına sağlama başarı oranı. Bir operatörün başarı oranı %95’in altına düşerse alarm tetiklenir.
Güvenlik Modeli
Her yerde mTLS. Tüm SM-DP+ iletişimi, operatör tarafından verilen istemci sertifikalarıyla karşılıklı TLS kullanır. Sertifikalar HashiCorp Vault’ta saklanır, başlangıçta sağlama pod’larına enjekte edilir ve süre dolmadan 30 gün önce yenilenir.
Profil şifreleme. eSIM profilleri hassas kimlik bilgileri (Ki, OPc değerleri) içerir. Bunlar SM-DP+ sunucusundan eUICC’ye uçtan uca şifrelenir. Backend’imiz şifresi çözülmüş profil içeriğini asla görmez — yalnızca meta verileri (ICCID, EID, durum) yönetiriz.
Denetim günlüğü. Her sağlama eylemi, her bakiye değişikliği ve her operatör API çağrısı korelasyon kimliği, kullanıcı kimliği, zaman damgası ve yanıt koduyla kaydedilir. Günlükler değiştirilemezdir (yalnızca yazılabilir bir nesne deposuna ekleme yapılır) ve telekomünikasyon düzenleme gereksinimlerine uygun olarak 7 yıl saklanır.
İzleme ve Gözlemlenebilirlik
Sağlama sistemi için üç temel SLI takip ediyoruz:
- Sağlama başarı oranı — Hedef: %99,2.
ProvisionProfileAPI çağrılarının 5 dakika içinde etkinleştirilmiş bir profille sonuçlanma yüzdesi olarak ölçülür. Şu anda ortalama %99,4. - Etkinleştirme süresi — Hedef: p95 90 saniyenin altında. API çağrısından ilk RADIUS
Access-Acceptmesajına kadar ölçülür. Güncel p95: 47 saniye. - Bakiye doğruluğu — Hedef: gerçek zamanlı tahminlerin kesinleşmiş CDR toplamlarının %3’ü içinde olması. Güncel ortalama fark: %1,1.
Her SLI bir hata bütçesini besler. Bütçe tükendiğinde (örneğin, sağlama başarı oranı kayan 7 günlük pencerede %99,2’nin altına düştüğünde), özellik dağıtımlarını dondurur ve güvenilirliğe odaklanırız.
OpenTelemetry ile dağıtık izleme, tam istek yolunu birbirine bağlar: Flutter uygulama çağrısı, API geçidi, sağlama servisi, SM-DP+ çağrısı, operatör geri çağrımı ve bakiye güncellemesi. Tek bir izleme kimliği isteği tüm sistemler boyunca takip eder; bu sayede olay araştırması, günlük dosyaları arasında zaman damgalarını eşleştirmek yerine tek bir dizgeyi aramaya dönüşür.
Üretimden Çıkarılan Dersler
Bu sistemi 150’den fazla ülkede üretimde çalıştırdıktan sonra, öne çıkan birkaç ders var:
Darboğaz operatör API’leridir, sizin kodunuz değil. Dahili gecikmemizi optimize etmek için aylar harcadıktan sonra, p99 sağlama süremizin %80’inin SM-DP+ yanıtlarını beklemekle geçtiğini fark ettik. Gerçek optimizasyon, zaman aşımı yönetimi ve yedek yönlendirmeyi iyileştirmekti.
Telekomünikasyonda idempotency isteğe bağlı değildir. Tek bir mükerrer sağlama isteği, maliyeti olan ve kullanıcının kafasını karıştıran yetim bir profil oluşturur. Idempotency anahtarları ilk haftada kendilerini amorti etti.
CDR uzlaştırması hiçbir zaman tam otomasyona ulaşmaz. %98 otomasyona ulaştık, ancak kalan %2 — saat dilimi sınır durumları, operatöre özgü CDR tuhaflıkları, bir ülkede etkinleşip aynı CDR periyodunda başka bir ülkeye dolaşıma geçen profiller — her zaman insan incelemesi gerektirir. Bunun için mühendislik zamanı ayırın.
Küresel bir kullandıkça öde eSIM ürünü için sağlama backend’i inşa etmek, aslında çok sağlayıcılı bir profil yönetim katmanı üzerine mini bir telekomünikasyon faturalandırma sistemi inşa etmektir. Standartlar (RSP, SGP.22, ES2+) size temel sağlar, ancak asıl mühendislik işi, tüm bunları kullanıcıya görünmez kılan yönlendirme, ölçümleme ve hata yönetimindedir.