Skip to content

GraphQL API Tasarımı ​

GraphQL, istemcinin ihtiyaç duyduğu alanları tek bir şema üzerinden seçmesini sağlar. Esneklik; şema yönetişimi, resolver maliyeti, yetkilendirme ve sorgu karmaşıklığı kontrol edilmediğinde operasyonel riske dönüşür.

Hızlı Karar ​

İhtiyaçGraphQL yaklaşımıDikkat
Farklı ekranların farklı alan ihtiyacıTek endpoint + typed schemaSorgu maliyeti sınırlandırılmalı
Komut işlemiMutationIdempotency ve hata modeli açık olmalı
Canlı güncellemeSubscriptionConnection ve fan-out maliyeti ölçülmeli
Birden fazla domainFederation veya compositionŞema sahipliği ve breaking change yönetimi gerekir

Üretim Kontrol Listesi ​

  • Problem: GraphQL, REST endpoint çoğalmasını veya over-fetching'i gerçekten azaltıyor mu?
  • Çözüm: Schema owner, resolver timeout'u, auth scope'u, complexity limiti ve cache stratejisi belli mi?
  • Trade-off: İstemci esnekliği artar; sorgu maliyeti ve gözlemlenebilirlik karmaşıklaşır.
  • Hata durumu: Partial data, resolver timeout, downstream failure ve subscription disconnect ele alınmalı.
  • Ölçüm: Operation name, query complexity, resolver latency, error path ve active connection sayısı izlenmeli.
  • Güvenlik/maliyet: Introspection, depth, alias ve batch abuse kontrolleri production politikasına bağlanmalı.

Schema-First Tasarım ​

Şema istemci ve sunucu arasındaki ana sözleşmedir. Type, field, nullability, enum, input ve hata davranışı birlikte tasarlanır:

graphql
type Order {
  id: ID!
  status: OrderStatus!
  items: [OrderItem!]!
}

type Query {
  order(id: ID!): Order
  orders(after: String, first: Int = 20): OrderConnection!
}

type Mutation {
  cancelOrder(input: CancelOrderInput!): CancelOrderPayload!
}

Alan eklemek genellikle geriye uyumludur; alan silmek, nullability değiştirmek veya anlamı değiştirmek breaking change olabilir. Federation kullanılıyorsa her subgraph kendi alanlarının sahibi olmalı ve ortak entity kimlikleri versioned contract ile yönetilmelidir.

Resolver, Mutation ve Subscription ​

Resolver yalnızca veri çekmez; auth context, timeout, batching ve hata dönüşümünü de taşır. Resolver içinde uzun zincirli senkron çağrılar oluşturmak yerine bounded parallelism ve downstream deadline kullan.

Mutation sonucu işlenen kaydın durumu, stable error code ve gerekiyorsa idempotency sonucu ile dönmelidir. Uzun işlerde mutation, job ID döndürüp istemciyi status query veya webhook akışına yönlendirebilir.

Subscription; bağlantı kimliği, authorization, heartbeat, reconnect, backpressure, tenant izolasyonu ve broker fan-out ile birlikte tasarlanır. Bağlantının kopması, olayın kaybolduğu veya tekrarlandığı anlamına gelebilir; event ID ve resume politikası belgelenmelidir.

DataLoader ve N+1 ​

Bir liste resolver'ı her öğe için ayrı downstream çağrı yaparsa N+1 oluşur. DataLoader, aynı request scope içinde anahtarları batch'leyerek çağrı sayısını azaltır; global cache gibi kullanılırsa kullanıcı/tenant izolasyonu bozulabilir.

java
@BatchMapping
Map<String, List<OrderItem>> items(List<Order> orders) {
    return itemService.findByOrderIds(
        orders.stream().map(Order::getId).toList());
}

Batch size, database IN sınırı, cache lifetime ve resolver timeout'u ölçülmeli; sadece DataLoader eklemek sorgu planı sorununu çözmez.

Directive, Yetkilendirme ve Complexity ​

Directive'ler @deprecated, field masking, tenant filtreleme ve özel politika işaretleri için kullanılabilir. Yetkilendirme yalnızca root query'de değil, her hassas field ve object seviyesinde uygulanmalıdır.

Depth limit, field cost, timeout, maximum aliases, pagination cap ve persisted query allowlist birlikte kullanılabilir. Operation name zorunlu tutulursa tracing ve maliyet analizi anlamlı hale gelir.

Cache ve Federation ​

GraphQL cache için field-level cache, normalized client cache, response cache ve persisted query/APQ farklı katmanlardır. Mutation sonrası hangi alanların invalidated olduğu, user/tenant scope'u ve stale data kabulü yazılmalıdır.

Federation, tek bir şemanın sahipliğini dağıtır; network hop, cross-subgraph failure, schema composition ve deploy sıralaması ekler. Federation; domain sınırları net değilse yalnızca dağıtık monolith oluşturur.

Sonuç ​

GraphQL başarısı endpoint sayısıyla değil; şema evrimi, resolver bütçesi, field-level authorization, N+1 kontrolü ve operation-level observability ile ölçülür. REST ile birlikte kullanılabilir; istemci ihtiyacı ve operasyon maliyeti kararın parçasıdır.

Eren Demir tarafından oluşturulmuştur.