API tasarımında 2015''ten beri süren bir tartışma: GraphQL mi, REST mi? Her ikisi de zengin production deneyimine sahip; fark felsefelerinde. Bu yazı iki yaklaşımı net kriterlerle karşılaştırır ve hangi senaryoda hangisinin daha uygun olduğunu gösterir.

Temel Fark

İlgili rehberler: REST API güvenlik · API rate limiting · KEYDAL API geliştirme hizmetleri

REST: Kaynak-odaklı (/users/42, /users/42/orders), HTTP verb''leri (GET/POST/PUT/DELETE), her endpoint sabit response shape. GraphQL: Query dili — client hangi alanları istediğini söyler, sunucu tam olarak onu döner. Tek endpoint (/graphql), POST ile query gönderilir.

# REST
GET /users/42
  → { id, name, email, phone, address, createdAt, ... }
GET /users/42/orders
  → [{ id, total, items, createdAt }, ...]

# GraphQL
POST /graphql
query {
  user(id: 42) {
    name
    email
    orders(last: 10) {
      id
      total
    }
  }
}
→ { data: { user: { name, email, orders: [...] } } }

GraphQL Avantajları

  • Over-fetching yok: Mobil uygulamada sadece name ve avatar lazım, 50 alanlı user object inmez
  • Under-fetching yok: Tek istekte kullanıcı + orders + items al, 3 ayrı REST çağrısına gerek yok
  • Strongly-typed schema: SDL (Schema Definition Language) ile tip güvenliği
  • Tooling: Apollo Studio, GraphiQL — auto-complete, docs otomatik
  • Subscription: Real-time güncellemeler WebSocket üzerinden

GraphQL Dezavantajları

  • Caching zor: Tek endpoint, POST — HTTP cache çalışmaz, client-side cache gerekir
  • N+1 problemi: Naive resolver yazımı DB''yi bombalar — DataLoader şart
  • Complexity: Schema, resolver, data source — REST''ten fazla moving parts
  • Monitoring zor: Tek endpoint''te 1000 farklı sorgu — route-based metric yok
  • Sorgu maliyeti kontrolsüz: Kötü niyetli deeply-nested query server''ı çökertir

REST Avantajları

  • Basit: Her developer bilir, öğrenme eğrisi düşük
  • HTTP semantics: Status code, method, header — yerleşik
  • Caching kolay: Cache-Control, CDN, browser cache çalışır
  • Tool ecosystem: curl, Postman, OpenAPI, SDK generator
  • Versioning kolay: /v1/users, /v2/users

N+1 Problemi ve DataLoader

// Naive resolver — N+1
const resolvers = {
    Post: {
        author: (post) => db.users.findByPk(post.authorId)
    }
};
// 100 post listeleyince 100 ayrı user query → DB çöker

// DataLoader ile batch + cache
const DataLoader = require('dataloader');
const userLoader = new DataLoader(async (ids) => {
    const users = await db.users.findAll({ where: { id: ids } });
    return ids.map(id => users.find(u => u.id === id));
});

const resolvers = {
    Post: {
        author: (post) => userLoader.load(post.authorId)
    }
};
// 100 post → tek DB query (WHERE id IN [...])

Schema Tasarımı (SDL)

type User {
    id: ID!
    email: String!
    name: String
    posts(limit: Int = 10, after: ID): PostConnection!
    role: Role!
}

enum Role { USER ADMIN MODERATOR }

type Post {
    id: ID!
    title: String!
    content: String!
    author: User!
    createdAt: DateTime!
}

type PostConnection {
    edges: [PostEdge!]!
    pageInfo: PageInfo!
}

type PostEdge {
    node: Post!
    cursor: String!
}

type Query {
    me: User
    user(id: ID!): User
    posts(limit: Int = 10): [Post!]!
}

type Mutation {
    createPost(input: CreatePostInput!): Post!
    deletePost(id: ID!): Boolean!
}

input CreatePostInput {
    title: String!
    content: String!
}

Sorgu Maliyeti Kontrolü

// Query depth limit
const depthLimit = require('graphql-depth-limit');
const server = new ApolloServer({
    typeDefs, resolvers,
    validationRules: [depthLimit(5)]  // max 5 seviye derinlik
});

// Query complexity
const { createComplexityLimitRule } = require('graphql-validation-complexity');
validationRules: [createComplexityLimitRule(1000)];

// Persisted queries — sadece whitelist'teki query'ler kabul
const persistedQueries = { 'abc123': 'query { me { id } }' };

Ne Zaman Hangisi?

GraphQL seçin:

  • Mobil app + web app aynı backend''den farklı veri istiyor
  • Çok sayıda nested resource: user → orders → items → products → reviews
  • Frontend ekibi büyük: Kendi query''lerini yazsınlar, backend değişmesin
  • Real-time: subscription feature
  • BFF (backend-for-frontend) deseninde

REST seçin:

  • Public API: 3. parti entegratorlara sunulan — REST evrensel
  • Simple CRUD: Admin panel, dashboard — GraphQL overkill
  • CDN caching kritik: Public içerik, yüksek trafik
  • Microservices arası: Servis servise REST/gRPC daha iyi
  • Ekibin deneyimi REST''te

Hibrit Yaklaşım

Çoğu modern uygulama ikisini birlikte kullanır: GraphQL client-facing API için, REST/gRPC mikroservis iç iletişimi için. BFF pattern''inde GraphQL gateway arkadaki REST servisleri çağırır.

Alternatif: tRPC

TypeScript monorepo''larda GraphQL''in getirdiği complexity''yi istemeyip REST''in esnekliğini arıyorsanız tRPC''ye bakın. Schema yok — TypeScript tipleri end-to-end type safety sağlar. Apollo''nun light rakibi.

API Tasarım Prensipleri ve Güvenli Endpoint Mimarisi

Profesyonel API tasarımı dört unsuru bir araya getirir: doğru protokol seçimi (REST CRUD için ideal, GraphQL flexible queries için, gRPC microservice-to-microservice için), kimlik doğrulama (OAuth 2.0 / OIDC, JWT access token, refresh token rotation), rate limiting (token bucket, sliding window, IP/user/API key bazlı) ve versiyonlama (URL versiyon /v1/, header versiyon, deprecation sürecleri). API endpoint güvenliği için input validation, prepared statement, CORS politikası, idempotency-key (POST için), webhook signature verification ve OpenAPI/Swagger dokümantasyonu modern standartlardır. Yüksek trafikli API'lerde Redis ile rate limit + cache, Kafka veya RabbitMQ ile asenkron iş kuyruğu, OpenTelemetry ile dağıtık izleme önerilir.

API tasarım danışmanlığı

GraphQL, REST veya tRPC seçimi ve API mimarisi için iletişime geçin

WhatsApp