Episode 8 menghubungkan GraphQL ke sumber data nyata: pola data source, integrasi SQL dengan Prisma, integrasi NoSQL dengan MongoDB dan Redis, class RESTDataSource untuk API eksternal, serta best practices separation of concerns antara resolver dan data layer.

Server GraphQL kalian sudah berjalan, tapi belum ada data nyata. Episode 8 mengubah itu: kita menghubungkan GraphQL ke database dan API eksternal. Inilah titik di mana GraphQL benar-benar berguna — mengambil data dari berbagai sumber dan menyajikannya dalam satu endpoint.
Kita akan membahas pola data source, integrasi SQL dengan Prisma, integrasi NoSQL dengan MongoDB, penggunaan Redis untuk caching, class RESTDataSource untuk mengonsumsi API eksternal, dan best practices separation of concerns antara resolver dan data layer.
Sebuah resolver bisa mengambil data dari mana saja. Empat pola yang paling umum:
RESTDataSource.Pola kuncinya tetap sama: resolver jangan berisi logika data langsung, melainkan mendelegasikan ke layer data yang terpisah. Inilah yang disebut separation of concerns.
Prisma adalah ORM modern untuk TypeScript yang menghasilkan tipe dari skema database — sangat cocok dipasangkan dengan GraphQL. Setup-nya:
npm install @prisma/client
npm install -D prisma
npx prisma initLalu definisikan model di schema.prisma:
model User {
id Int @id @default(autoincrement())
username String @unique
email String @unique
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
body String
authorId Int
author User @relation(fields: [authorId], references: [id])
}Jalankan npx prisma migrate dev untuk membuat tabel, lalu masukkan client Prisma ke context:
import { PrismaClient } from "@prisma/client";
const prisma = new PrismaClient();
const server = new ApolloServer({
typeDefs,
resolvers,
});
const { url } = await startStandaloneServer(server, {
context: async () => ({ prisma }),
});Resolver kini bisa memakai ctx.prisma:
Query: {
post: (_, args, ctx) =>
ctx.prisma.post.findUnique({ where: { id: Number(args.id) } }),
},Di production, gunakan connection pooling seperti PgBouncer, dan buat query yang selektif agar tidak mengambil kolom berlebihan. Masalah N+1 yang timbul dari pola resolver chain akan diselesaikan dengan DataLoader di episode 9.
Untuk database dokumen, gunakan MongoDB dengan Mongoose:
npm install mongooseimport { Schema, model } from "mongoose";
const userSchema = new Schema({
username: { type: String, required: true, unique: true },
email: String,
});
export const User = model("User", userSchema);Redis sangat berguna sebagai cache layer antara resolver dan database. Pola yang umum: cek cache dulu, jika kosong ambil dari database lalu simpan ke cache dengan TTL. Kita akan membedah strategi caching menyeluruh di episode 20, termasuk cara memakai Redis untuk menyimpan hasil query.
Untuk mengonsumsi REST API dari dalam resolver, Apollo menyediakan class RESTDataSource. Ini memberikan batching otomatis, caching per request, dan de-duplikasi request yang sangat berguna:
import { RESTDataSource } from "@apollo/datasource-rest";
export class UsersAPI extends RESTDataSource {
baseURL = "https://api.example.com/";
async getUser(id) {
return this.get(`users/${id}`);
}
async getPostsByUser(userId) {
return this.get("posts", { params: { userId } });
}
}Instansiasi data source ini lalu taruh di context. Pola ini adalah fondasi strategi migrasi REST ke GraphQL di episode 47 — REST API yang sudah ada bisa dibungkus tanpa ditulis ulang.
Prinsip utama: resolver tetap tipis dan hanya mengatur "cara client meminta data", sementara layer data mengatur "dari mana data didapat". Implementasi praktisnya:
import { UserRepository } from "./data/user.repository";
const resolvers = {
Query: {
user: (_, args, ctx) => ctx.repos.users.findById(args.id),
},
};Pola ini membuat resolver mudah dites (episode 21), mudah diganti sumber datanya, dan mudah dioptimasi secara terpusat.
Inti yang harus dibawa pulang:
RESTDataSource membungkus API eksternal dengan batching dan caching otomatis.Di episode 9 selanjutnya kalian akan mempelajari DataLoader dan N+1 problem — apa itu N+1, mengapa GraphQL mudah memicunya, cara batching dan caching dengan DataLoader, integrasi loader ke dalam context per request, hingga teknik memonitor perbaikan performa. Masalah klasik GraphQL akan kalian taklukkan!