Tip Güvenliği Yöntemi: TS Çıkarımı vs Şema + Codegen
tRPC hiçbir ayrı şema dosyası tutmaz — sözleşmenin kendisi, sunucudaki AppRouter TypeScript tipidir. İstemci bu tipi doğrudan içe aktarır (import type { AppRouter } from './server') ve derleyici, sunucu prosedürü değiştiğinde istemci kodunu anında kırar; resmi site bunu 'dosyayı kaydetmeden önce hatayı görürsün' diye özetliyor (trpc.io). Codegen adımı, ara build süreci veya runtime şema doğrulaması yoktur — bu da tRPC'nin 'no build or compile steps' iddiasının temelidir. GraphQL ise tam tersi bir model kurar: SDL (Schema Definition Language) ile yazılmış bağımsız bir şema dosyası vardır, istemci tarafı tip güvenliği GraphQL Code Generator veya Relay compiler gibi ayrı bir codegen adımıyla sağlanır. Bu fark, günlük geliştirme akışını doğrudan belirler: tRPC'de 'sunucu kodu = sözleşme', GraphQL'de 'şema dosyası = sözleşme, kod her iki taraftan bu sözleşmeye uyar'.
Çoklu İstemci Desteği: Monorepo Bağımlılığı vs Dil-Bağımsızlık
tRPC'nin tip paylaşımı, sunucu ve istemcinin aynı TypeScript monorepo'sunda yaşamasını gerektirir. Native mobil (Swift/Kotlin) veya bağımsız üçüncü parti istemciler bu avantajdan yararlanamaz; dış tüketiciye açılmak istersen trpc-to-openapi gibi topluluk paketiyle REST/OpenAPI yüzeyine dönüştürmen gerekir — bu tRPC çekirdeğinin değil, ek bir katmanın işidir. GraphQL ise baştan dil-bağımsız bir şema sözleşmesiyle tasarlanmıştır: iOS, Android, web ve üçüncü parti her istemci aynı GraphQL uç noktasına, kendi diline uygun bir GraphQL client kütüphanesiyle (Apollo Client, Relay, urql) bağlanabilir. Relay, Meta'nın kendi resmi istemcisi olarak alan-bazlı deduplikasyon ve otomatik güncel kalma sağlıyor (relay.dev). Sonuç: tek web istemcisi + tek TS kod tabanında tRPC'nin avantajı monorepo dışına taştığında kaybolur; GraphQL bu sınırı baştan aşar.
Şema Sözleşmesi ve Versiyonlama
GraphQL şeması introspection ile keşfedilebilir — GraphiQL gibi araçlar şemayı canlı olarak gösterir, dış geliştirici hiçbir kod paylaşımı olmadan API'yi anlayabilir. Versiyonlama, ayrı bir '/v2' uç noktası açmak yerine deprecation mekanizmasıyla yapılır: alan @deprecated işaretlenir, istemciler kademeli geçer, kırıcı değişiklik gerekmez (graphql.org/faq). tRPC'de ayrı bir 'şema' kavramı yoktur; sözleşme = TypeScript router tipinin kendisidir. Bu, aynı kod tabanı içinde son derece pratik ve hızlıdır, ama 'formel, dışa açık bir API sözleşmesi' kavramı GraphQL kadar olgun değildir — versiyonlama, prosedür isimlendirme disiplinine ve elle yönetilen deprecation yorumlarına kalır.
Over/Under-Fetching ve Caching Modeli
GraphQL'in temel tasarım amacı over/under-fetching'i çözmektir: istemci ihtiyacı olan alanları tam olarak seçer, ne eksik ne fazla veri gelir. Ancak bu esneklik bir bedel getirir — GraphQL'de REST'teki gibi URL-bazlı bir cache primitive'i yoktur; resmi kaynak, API'nin global olarak benzersiz bir ID expose etmesini 'best practice' olarak öneriyor, bu da Relay/Apollo'nun normalize edilmiş client-cache modelinin temelidir (graphql.org/learn/caching). tRPC'de her prosedürün dönüş tipi sabittir — alan-bazlı seçim yoktur, ama TanStack Query'nin queryKey tabanlı cache modeli doğrudan ve native kullanılır; httpBatchLink ile birden fazla çağrı tek HTTP isteğinde gruplanarak standart HTTP semantiğine daha yakın durulur. Kısacası: GraphQL esnek veri seçimi karşılığında cache karmaşıklığı öder, tRPC basit HTTP-cache dostu bir model karşılığında alan-seçim esnekliğinden vazgeçer.
N+1 Sorunu ve Dataloader İhtiyacı
GraphQL'in resolver mimarisi, iç içe alanları çözerken doğal olarak N+1 sorgu riskini doğurur — her posts alanı için ayrı bir author sorgusu tetiklenebilir. Bunu çözmek için GraphQL Foundation'ın resmi graphql/dataloader paketi (13.390 yıldız, MIT) batching ve request-scoped caching sağlar; bu, GraphQL sunucusu yazarken disiplinle uygulanması gereken bir mimari pratiktir. tRPC'de prosedür-bazlı yapı nedeniyle N+1 riski aynı ölçüde yapısal değildir — bir prosedür kendi veri erişimini tek bir fonksiyon gövdesinde yönetir, ama karmaşık iç içe veri getirme senaryolarında yine de elle batching (örn. aynı Prisma sorgusunu birleştirme) gerekebilir. Fark, GraphQL'de bunun resmi, adı konmuş bir problem sınıfı ve resmi çözüm paketi olması; tRPC'de ise genel backend mühendisliği pratiğine bırakılmasıdır.
Araç Ekosistemi ve Public API Yayınlanabilirliği
GraphQL tarafında Apollo (GraphOS, Router, Federation) ve Relay gibi olgun, kurumsal ürünler var; Apollo GraphOS'un ücretsiz katmanı dakikada 60 istek ve 1 gün veri saklama ile sınırlı, Developer planı milyon istek başına 5 dolardan başlıyor, Standard/Enterprise özel fiyatlandırmayla 90 gün–18 ay retention ve federasyon desteği sunuyor (apollographql.com/pricing). tRPC ekosistemi ise TanStack Query + topluluk paketlerine (trpc-to-openapi, trpc-ui) dayanır; resmi ücretli bir SaaS katmanı yoktur, tamamen kendi barındırılan açık kaynak bir kütüphanedir. Public API yayınlanabilirlik açısından GraphQL'in introspection'ı ve Apollo Studio/GraphOS'un şema kayıt sistemi dış geliştiricilere doğal bir sözleşme sunar; tRPC bu senaryoda ek bir REST/OpenAPI katmanına ihtiyaç duyar.