Episode 30 membandingkan dua pendekatan membangun schema: schema-first dengan SDL dan code-first dengan library seperti Type-GraphQL dan Pothos. Kalian belajar class-based schema dengan decorators, dependency injection, plugin Pothos, dan panduan memilih sesuai kebutuhan tim dan project.

Selama ini kalian menulis schema sebagai file SDL terpisah — itu pendekatan schema-first. Episode 30 memperkenalkan pendekatan alternatif: code-first, di mana schema dihasilkan langsung dari kode TypeScript.
Kita akan membandingkan kedua filosofi, mempraktikkan Type-GraphQL dengan decorators dan dependency injection, melihat Pothos sebagai penerus modern, lalu menutup dengan panduan memilih pendekatan yang tepat.
Pendekatan schema-first (yang kalian pakai di episode 3-7) menempatkan file SDL sebagai sumber kebenaran, lalu resolver dipasangkan ke schema:
type Query {
users: [User!]!
}
type User {
id: ID!
username: String!
}Kelebihannya: schema mudah direview non-programmer, kolaborasi dengan frontend dimulai sebelum backend (via mock, episode 29), dan bahasa-agnostik. Kekurangannya: duplikasi antara SDL dan tipe TypeScript, serta penulisan resolver map manual yang rawan salah tipe tanpa codegen.
Schema-first modern biasanya dipasangkan dengan GraphQL Code Generator (episode 23) agar tipe TypeScript dihasilkan otomatis dari SDL — mengatasi sebagian besar kekurangannya.
Pendekatan code-first membalik arah: kalian menulis kelas TypeScript dengan decorators, dan schema GraphQL dihasilkan dari kode tersebut. Tidak ada duplikasi — tipe TypeScript adalah satu-satunya sumber kebenaran:
npm install type-graphql graphql class-validator reflect-metadataimport { ObjectType, Field, ID } from "type-graphql";
@ObjectType()
export class User {
@Field(() => ID)
id: string;
@Field()
username: string;
}Perhatikan bahwa @Field() mendefinisikan field schema, dan resolvernya juga sebagai method di kelas:
import { Resolver, Query, Arg } from "type-graphql";
@Resolver()
export class UserResolver {
@Query(() => User)
async user(@Arg("id") id: string) {
return this.userService.findById(id);
}
}Class resolver memungkinkan dependency injection — dependensi disuntikkan ke constructor, membuat kode mudah dites:
import { Service } from "typedi";
@Service()
@Resolver()
export class UserResolver {
constructor(private userService: UserService) {}
}Buat schema dari seluruh resolvers:
import { buildSchema } from "type-graphql";
const schema = await buildSchema({
resolvers: [UserResolver, PostResolver],
container: Container,
});Dengan Container dari typedi, seluruh graph of dependency dikelola otomatis. Ini membuat Type-GraphQL sangat populer untuk aplikasi besar yang terstruktur.
Pothos adalah pendekatan code-first yang lebih baru dengan type safety tingkat lanjut dan sistem plugin:
npm install @pothos/coreimport SchemaBuilder from "@pothos/core";
const builder = new SchemaBuilder({});
builder.objectType("User", {
fields: (t) => ({
id: t.exposeID("id"),
username: t.exposeString("username"),
posts: t.field({
type: [Post],
resolve: (user) => db.posts.findByAuthor(user.id),
}),
}),
});
const schema = builder.toSchema();Pothos unggul dalam type inference — tipe resolver otomatis ditarik dari implementasi — dan plugin untuk prisma, relay, scope auth, dan banyak lagi. Migration dari Nexus cukup lurus karena pola-penulisan yang mirip.
schema-first -> kolaborasi lintas tim, bahasa campuran
code-first -> TypeScript penuh, struktur besar, DIPertimbangan tambahan: ukuran tim dan kompleksitas project. Tim kecil dengan TypeScript penuh cenderung memilih code-first; enterprise dengan banyak konsumen dan review schema ketat sering memilih schema-first plus codegen. Tidak ada jawaban salah mutlak — konsistensi lebih penting daripada pilihan itu sendiri.
Inti yang harus dibawa pulang:
Di episode 31 selanjutnya kalian akan mempelajari deployment GraphQL ke production — platform deployment seperti Vercel, Railway, dan Render, containerization dengan Docker multi-stage, Kubernetes, pertimbangan serverless seperti cold start, manajemen environment dan secrets, hingga strategi database migrations. API kalian akan melangkah ke production!