Pahami kekangan REST Roy Fielding dan bagaimana mereka membentuk desain API dan aplikasi web praktis: client-server, stateless, caching, antarmuka seragam, sistem berlapis, dan lainnya.

Roy Fielding bukan sekadar nama yang melekat pada buzzword API. Ia adalah salah satu penulis kunci spesifikasi HTTP dan URI dan, dalam disertasinya, mendeskripsikan sebuah gaya arsitektural bernama REST (Representational State Transfer) untuk menjelaskan mengapa Web bekerja sebagus itu.
Asal-usul itu penting karena REST tidak diciptakan untuk membuat “endpoint yang enak dilihat.” Ia adalah cara menjelaskan kekangan yang memungkinkan jaringan global yang berantakan tetap dapat diskalakan: banyak klien, banyak server, perantara, caching, kegagalan parsial, dan perubahan berkelanjutan.
Jika Anda pernah bertanya-tanya mengapa dua “REST API” terasa sama sekali berbeda—atau mengapa pilihan desain kecil kemudian berubah menjadi masalah paginasi, kebingungan caching, atau perubahan yang memecah—panduan ini dimaksudkan untuk mengurangi kejutan tersebut.
Anda akan mendapatkan:
REST bukanlah checklist, protokol, atau sertifikasi. Fielding menggambarkannya sebagai sebuah gaya arsitektural: sekumpulan kekangan yang, bila diterapkan bersama, menghasilkan sistem yang diskala seperti Web—mudah digunakan, dapat berevolusi dari waktu ke waktu, dan ramah terhadap perantara (proxy, cache, gateway) tanpa koordinasi konstan.
Web awal harus bekerja antar banyak organisasi, server, jaringan, dan tipe klien. Ia harus tumbuh tanpa kontrol pusat, bertahan dari kegagalan parsial, dan memungkinkan fitur baru muncul tanpa memecah yang lama. REST menghadapi itu dengan memilih sejumlah kecil konsep yang banyak dibagi (seperti pengidentifikasi, representasi, dan operasi standar) daripada kontrak khusus yang terikat erat.
Kekangan adalah aturan yang membatasi kebebasan desain demi keuntungan. Misalnya, Anda mungkin mengorbankan status sesi sisi-server agar permintaan dapat ditangani oleh node server mana pun, yang meningkatkan keandalan dan skalabilitas. Setiap kekangan REST membuat pertukaran serupa: kurang fleksibilitas ad-hoc, lebih banyak prediktabilitas dan kemampuan berevolusi.
Banyak API HTTP meminjam ide REST (JSON lewat HTTP, endpoint URL, mungkin status code) tetapi tidak menerapkan semua kekangan. Itu tidak selalu “salah”—sering mencerminkan tenggat produk atau kebutuhan internal. Penting untuk menamai perbedaannya: sebuah API bisa berorientasi sumber daya tanpa sepenuhnya REST.
Pikirkan sistem REST sebagai sumber daya (hal yang dapat Anda beri nama dengan URL) yang klien berinteraksi melalui representasi (tampilan saat ini dari sumber daya, seperti JSON atau HTML), dipandu oleh tautan (langkah berikutnya dan sumber daya terkait). Klien tidak butuh aturan rahasia di luar band; ia mengikuti semantik standar dan bernavigasi menggunakan tautan, sama seperti browser menavigasi Web.
Sebelum tersesat dalam kekangan dan detail HTTP, REST dimulai dengan pergeseran kosakata sederhana: pikirkan sumber daya, bukan aksi.
Sebuah sumber daya adalah “benda” yang dapat diberi alamat dalam sistem Anda: pengguna, faktur, kategori produk, keranjang belanja. Bagian pentingnya adalah bahwa itu adalah kata benda dengan identitas.
Itu sebabnya /users/123 dibaca secara alami: ia mengidentifikasi pengguna dengan ID 123. Bandingkan dengan URL berbentuk aksi seperti /getUser atau /updateUserPassword. Itu menggambarkan kata kerja—operasi—bukan benda yang Anda operasikan.
REST tidak mengatakan Anda tidak boleh melakukan tindakan. Ia mengatakan tindakan harus diekspresikan melalui antarmuka seragam (untuk API HTTP, biasanya berarti metode seperti GET/POST/PUT/PATCH/DELETE) yang bekerja pada pengidentifikasi sumber daya.
Sebuah representasi adalah apa yang Anda kirim di jaringan sebagai snapshot atau tampilan dari sumber daya pada suatu titik waktu. Sumber daya yang sama dapat memiliki beberapa representasi.
Contoh: sumber daya /users/123 bisa direpresentasikan sebagai JSON untuk aplikasi, atau HTML untuk browser.
GET /users/123
Accept: application/json
Mungkin mengembalikan:
{
"id": 123,
"name": "Asha",
"email": "[email protected]"
}
Sementara:
GET /users/123
Accept: text/html
Mungkin mengembalikan halaman HTML yang merender detail pengguna yang sama.
Ide utamanya: sumber daya bukan JSON dan bukan juga HTML. Itu hanyalah format untuk merepresentasikannya.
Setelah Anda memodelkan API di sekitar sumber daya dan representasi, beberapa keputusan praktis menjadi lebih mudah:
/users/123 tetap valid meski UI, alur kerja, atau model data Anda berevolusi.Mindset berorientasi sumber daya ini adalah fondasi yang dibangun oleh kekangan REST. Tanpanya, “REST” sering mereduksi menjadi “JSON lewat HTTP dengan beberapa pola URL yang rapi.”
Pemisahan klien–server adalah cara REST menegakkan pembagian tanggung jawab yang bersih. Klien fokus pada pengalaman pengguna (apa yang dilihat dan dilakukan orang), sementara server fokus pada data, aturan, dan persistensi (apa yang benar dan diperbolehkan). Saat Anda memisahkan kepentingan ini, masing-masing sisi bisa berubah tanpa memaksa penulisan ulang sisi lain.
Dalam istilah sehari-hari, klien adalah “lapisan presentasi”: layar, navigasi, validasi form untuk umpan balik cepat, dan perilaku UI optimis (misalnya menampilkan komentar baru segera). Server adalah “sumber kebenaran”: autentikasi, otorisasi, aturan bisnis, penyimpanan data, auditing, dan apa pun yang harus konsisten di seluruh perangkat.
Aturan praktis: jika sebuah keputusan memengaruhi keamanan, uang, izin, atau konsistensi data bersama, itu seharusnya berada di server. Jika keputusan hanya memengaruhi rasa pengalaman (tata letak, petunjuk input lokal, status pemuatan), itu berada di klien.
Kekangan ini langsung cocok dengan pengaturan umum:
Pemisahan klien–server membuat “satu backend, banyak frontend” menjadi realistis.
Kesalahan umum adalah menyimpan status alur UI di server (mis. “langkah checkout yang sedang dilalui pengguna”) dalam sesi sisi-server. Itu mengikat backend ke alur layar tertentu dan menyulitkan skalabilitas.
Lebih baik mengirim konteks yang diperlukan bersama setiap permintaan (atau menurunkannya dari sumber daya yang tersimpan), sehingga server tetap fokus pada sumber daya dan aturan—bukan mengingat bagaimana UI tertentu berjalan.
Statelessness berarti server tidak perlu mengingat apa pun tentang klien antar permintaan. Setiap permintaan membawa semua informasi yang diperlukan untuk memahaminya dan merespons dengan benar—siapa pemanggil, apa yang mereka inginkan, dan konteks yang diperlukan untuk memprosesnya.
Saat permintaan independen, Anda bisa menambah atau menghapus server di balik load balancer tanpa khawatir “server mana yang tahu sesi saya.” Itu meningkatkan skalabilitas dan ketahanan: instance mana pun bisa menangani permintaan mana pun.
Ini juga menyederhanakan operasi. Debugging sering lebih mudah karena konteks lengkap terlihat di permintaan (dan log), bukan tersembunyi di memori sesi server.
API stateless biasanya mengirim sedikit data lebih banyak per panggilan. Alih-alih bergantung pada sesi server yang tersimpan, klien menyertakan kredensial dan konteks setiap kali.
Anda juga harus eksplisit tentang alur pengguna yang “stateful” (seperti paginasi atau checkout multi-langkah). REST tidak melarang pengalaman multi-langkah—ia hanya mendorong agar status berada di klien atau di sumber daya sisi-server yang diidentifikasi dan dapat diambil kembali.
Authorization: Bearer … sehingga server mana pun bisa mengautentikasi.Idempotency-Key agar retry tidak menggandakan kerja.X-Correlation-Id memungkinkan pelacakan satu aksi pengguna di seluruh layanan dan log, bahkan di sistem terdistribusi.Untuk paginasi, hindari “server mengingat halaman 3.” Pilih parameter eksplisit seperti ?cursor=abc atau tautan next yang bisa diikuti klien, menjaga status navigasi di respons alih-alih di memori server.
Caching adalah tentang menggunakan kembali respons sebelumnya dengan aman sehingga klien (atau sesuatu di antaranya) tidak perlu meminta server Anda melakukan kerja yang sama lagi. Jika dilakukan dengan baik, ini mengurangi latensi bagi pengguna dan menurunkan beban untuk Anda—tanpa mengubah makna API.
Sebuah respons dapat dicache ketika aman bagi permintaan lain menerima payload yang sama untuk periode waktu tertentu. Dalam HTTP, Anda mengkomunikasikan niat itu dengan header caching:
Cache-Control: pengatur utama (berapa lama menyimpan, apakah boleh disimpan oleh cache bersama, dll.)ETag dan Last-Modified: validator yang memungkinkan klien menanyakan “apakah ini berubah?” dan mendapat jawaban murah “tidak berubah”Expires: cara lama untuk menyatakan kesegaran, masih ditemuiIni lebih besar daripada “caching browser.” Proxy, CDN, API gateway, dan bahkan aplikasi mobile bisa menggunakan kembali respons jika aturannya jelas.
Kandidat bagus:
Biasanya buruk:
private)Ide kuncinya: caching bukan pemikiran belakangan. Ia adalah kekangan REST yang memberi penghargaan pada API yang mengomunikasikan kesegaran dan validasi dengan jelas.
Antarmuka seragam sering disalahartikan sebagai “gunakan GET untuk baca dan POST untuk buat.” Itu hanya sebagian kecil. Gagasan Fielding lebih luas: API harus terasa konsisten sehingga klien tidak memerlukan pengetahuan khusus per-endpoint untuk menggunakannya.
Identifikasi sumber daya: Anda menamai benda (sumber daya) dengan pengidentifikasi yang stabil (biasanya URL), bukan aksi. Pikirkan /orders/123, bukan /createOrder.
Manipulasi melalui representasi: Klien mengubah sumber daya dengan mengirim representasi (JSON, HTML, dll.). Server mengontrol sumber daya; klien menukar representasi darinya.
Pesan yang menjelaskan diri sendiri: Setiap permintaan/respons harus membawa cukup informasi untuk diproses—metode, status code, header, media type, dan body yang jelas. Jika makna tersembunyi di dokumentasi luar-band, klien menjadi terikat erat.
Hypermedia (HATEOAS): Respons harus menyertakan tautan dan aksi yang diperbolehkan sehingga klien bisa mengikuti alur tanpa meng-hardcode setiap pola URL.
Antarmuka yang konsisten membuat klien kurang bergantung pada detail internal server. Seiring waktu, itu berarti lebih sedikit breaking change, lebih sedikit “kasus khusus,” dan lebih sedikit pengerjaan ulang saat tim mengubah endpoint.
200 untuk baca berhasil, 201 untuk sumber daya dibuat (dengan Location), 400 untuk masalah validasi, 401/403 untuk auth, 404 ketika sumber daya tidak ada.code, message, details, requestId.Content-Type, header caching), sehingga pesan menjelaskan dirinya sendiri.Antarmuka seragam tentang prediktabilitas dan kemampuan berevolusi, bukan hanya “kata kerja yang benar.”
Pesan “yang menjelaskan diri sendiri” adalah pesan yang memberi tahu penerima bagaimana menginterpretasikannya—tanpa memerlukan pengetahuan luar-band. Jika klien (atau perantara) tidak bisa memahami apa arti respons hanya dengan melihat header HTTP dan body, Anda telah membuat protokol privat yang berjalan di atas HTTP.
Kemenangan termudah adalah eksplisit dengan Content-Type (apa yang Anda kirim) dan sering Accept (apa yang Anda mau kembali). Respons dengan Content-Type: application/json memberi tahu klien aturan parsing dasar, tetapi Anda bisa melangkah lebih jauh dengan media type vendor atau profil saat makna penting.
Contoh pendekatan:
application/json dengan skema yang dipertahankan. Paling mudah untuk banyak tim.application/vnd.acme.invoice+json untuk menandakan representasi spesifik.application/json, tambahkan parameter profile atau tautan ke profil yang mendefinisikan semantik.Versioning harus melindungi klien yang sudah ada. Opsi populer:
/v1/orders): jelas, tetapi bisa mendorong pemisahan representasi daripada mengembangkannya.Accept): menjaga URL stabil dan membuat “apa artinya” menjadi bagian dari pesan.Apa pun pilihan Anda, bidik kompatibilitas mundur secara default: jangan ganti nama field sembarang, jangan ubah makna diam-diam, dan anggap penghapusan sebagai breaking change.
Klien belajar lebih cepat ketika error terlihat sama di mana-mana. Pilih satu bentuk error (mis. code, message, details, traceId) dan gunakan di seluruh endpoint. Gunakan nama field yang jelas dan prediktabel (createdAt vs. created_at) dan patuhi satu konvensi.
Dokumentasi bagus mempercepat adopsi, tetapi tidak bisa menjadi satu-satunya tempat makna berada. Jika klien harus membaca wiki untuk tahu apakah status: 2 berarti “lunas” atau “menunggu”, pesan itu tidak menjelaskan dirinya sendiri. Header yang dirancang baik, media type, dan payload yang terbaca mengurangi ketergantungan tersebut dan memudahkan evolusi sistem.
Hypermedia (disingkat HATEOAS: Hypermedia As The Engine Of Application State) berarti klien tidak perlu “tahu” URL selanjutnya di muka. Sebaliknya, setiap respons menyertakan langkah berikutnya yang dapat ditemukan sebagai tautan: ke mana pergi selanjutnya, aksi yang mungkin, dan kadang metode HTTP yang harus digunakan.
Alih-alih meng-hardcode jalur seperti /orders/{id}/cancel, klien mengikuti tautan yang disediakan server. Server pada dasarnya mengatakan: “Dengan status sumber daya saat ini, ini adalah langkah valid.”
{
"id": "ord_123",
"status": "pending",
"total": 49.90,
"_links": {
"self": { "href": "/orders/ord_123" },
"payment":{ "href": "/orders/ord_123/payment", "method": "POST" },
"cancel": { "href": "/orders/ord_123", "method": "DELETE" }
}
}
Jika pesanan berubah menjadi paid, server mungkin berhenti menyertakan cancel dan menambah refund—tanpa memecah klien yang berperilaku baik.
Hypermedia bersinar ketika alur berevolusi: langkah onboarding, checkout, persetujuan, langganan, atau proses apa pun di mana “aksi berikutnya” berubah berdasarkan status, izin, atau aturan bisnis.
Ia juga mengurangi URL yang di-hardcode dan asumsi klien yang rapuh. Anda bisa merestrukturisasi route, memperkenalkan aksi baru, atau menghapus yang lama sambil menjaga klien berfungsi selama makna relasi tautan tetap terjaga.
Tim sering melewatkan HATEOAS karena terasa seperti kerja ekstra: mendefinisikan format tautan, menyepakati nama relasi, dan mengajari pengembang klien mengikuti tautan daripada membangun URL. Yang hilang adalah manfaat REST utama: keterikatan longgar. Tanpa hypermedia, banyak API menjadi “RPC lewat HTTP”—menggunakan HTTP, tetapi klien tetap bergantung pada dokumentasi luar-band dan template URL tetap.
Sistem berlapis berarti klien tidak perlu tahu (dan sering tidak dapat mengetahui) apakah ia sedang berkomunikasi dengan server origin “nyata” atau dengan perantara di sepanjang jalan. Lapisan tersebut bisa mencakup API gateway, reverse proxy, CDN, layanan otentikasi, WAF, service mesh, dan bahkan routing internal antar microservice.
Lapisan menciptakan batasan yang bersih. Tim keamanan bisa menegakkan TLS, rate limit, autentikasi, dan validasi permintaan di edge tanpa mengubah setiap layanan backend. Tim operasi bisa melakukan scale horizontal di balik gateway, menambah caching di CDN, atau mengalihkan lalu lintas saat insiden. Bagi klien, ini menyederhanakan: satu endpoint API stabil, header konsisten, dan format error yang dapat diprediksi.
Perantara dapat memperkenalkan latensi tersembunyi (hop ekstra, handshake ekstra) dan menyulitkan debugging: bug mungkin ada di aturan gateway, cache CDN, atau kode origin. Caching juga bisa membingungkan saat lapisan berbeda meng-cache secara berbeda, atau ketika gateway menulis ulang header yang memengaruhi cache key.
Lapisan kuat—asal sistem tetap dapat diamati dan dapat diprediksi.
Code-on-demand adalah satu-satunya kekangan REST yang secara eksplisit opsional. Ini berarti server bisa memperluas klien dengan mengirim kode yang dapat dieksekusi yang berjalan di sisi klien. Alih-alih mengirim semua perilaku di klien sebelumnya, klien dapat mengunduh logika baru sesuai kebutuhan.
Jika Anda pernah memuat halaman web yang kemudian menjadi interaktif—memvalidasi form, merender grafik, memfilter tabel—Anda sudah menggunakan code-on-demand. Server mengirim HTML dan data, plus JavaScript yang berjalan di browser untuk menyediakan perilaku.
Ini alasan besar mengapa web bisa berevolusi cepat: browser tetap menjadi klien umum, sementara situs mengirim fungsionalitas baru tanpa memaksa pengguna menginstal aplikasi baru.
REST tetap “berfungsi” tanpa code-on-demand karena kekangan lain sudah memungkinkan skalabilitas, kesederhanaan, dan interoperabilitas. API bisa murni berorientasi sumber daya—melayani representasi seperti JSON—sementara klien mengimplementasikan perilakunya sendiri.
Banyak API modern sengaja menghindari pengiriman kode eksekusi karena mempersulit:
Code-on-demand berguna bila Anda mengendalikan lingkungan klien dan perlu meluncurkan perilaku UI dengan cepat, atau ketika Anda ingin klien tipis yang mengunduh “plugin” atau aturan dari server. Tapi anggaplah itu alat tambahan, bukan keharusan.
Intinya: Anda bisa sepenuhnya mengikuti REST tanpa code-on-demand—dan banyak API produksi memang demikian—karena kekangan itu bersifat ekstensi opsional, bukan fondasi interaksi berbasis sumber daya.
Kebanyakan tim tidak menolak REST—mereka mengadopsi gaya “REST-ish” yang menjaga HTTP sebagai transport sambil diam-diam menghapus kekangan penting. Itu bisa saja baik, asalkan itu adalah trade-off yang disengaja, bukan kecelakaan yang muncul kemudian sebagai klien rapuh dan penulisan ulang yang mahal.
Beberapa pola sering muncul:
/doThing, /runReport, /users/activate—mudah dinamai, mudah dipasang./createOrder, /updateProfile, /deleteItem—metode HTTP menjadi remeh.Pilihan ini sering terasa produktif di awal karena mencerminkan nama fungsi internal dan operasi bisnis.
Gunakan ini sebagai tinjauan “seberapa REST kita, sebenarnya?”:
/orders/{id} daripada /createOrder.Cache-Control, ETag, dan Vary untuk respons GET.Kekangan REST bukan sekadar teori—mereka adalah pembatas yang Anda rasakan saat merilis. Saat Anda menghasilkan API cepat (mis. menscaffold frontend React dengan backend Go + PostgreSQL), kesalahan termudah adalah membiarkan “apa pun yang tercepat dipasang” menentukan antarmuka Anda.
Jika Anda memakai platform vibe-coding seperti Koder.ai untuk membangun web app dari chat, membantu untuk membawa kekangan REST ini ke dalam percakapan sejak dini—menamai sumber daya dulu, tetap tanpa status, mendefinisikan bentuk error konsisten, dan memutuskan di mana caching aman. Dengan begitu, iterasi cepat masih menghasilkan API yang dapat diprediksi bagi klien dan lebih mudah dikembangkan. (Dan karena Koder.ai mendukung ekspor kode sumber, Anda bisa terus menyempurnakan kontrak API dan implementasinya saat kebutuhan berkembang.)
Tentukan sumber daya utama Anda terlebih dahulu, lalu pilih kekangan secara sadar: jika Anda melewatkan caching atau hypermedia, dokumentasikan mengapa dan apa yang Anda gunakan sebagai gantinya. Tujuannya bukan kemurnian—melainkan kejelasan: pengidentifikasi sumber daya yang stabil, semantik yang dapat diprediksi, dan trade-off eksplisit yang menjaga klien tangguh seiring sistem Anda berevolusi.
REST (Representational State Transfer) adalah sebuah gaya arsitektural yang dijelaskan Roy Fielding untuk menjelaskan mengapa Web dapat diskalakan.
Ini bukan protokol atau sertifikasi—melainkan sekumpulan kekangan (client–server, statelessness, cacheability, uniform interface, layered system, dan optional code-on-demand) yang menukar sebagian fleksibilitas demi skalabilitas, kemampuan berevolusi, dan interoperabilitas.
Karena banyak API hanya mengadopsi sebagian ide REST (misalnya JSON lewat HTTP dan URL yang rapi) sementara melewatkan kekangan lain (seperti aturan cache atau hypermedia).
Dua API yang disebut “REST” bisa terasa sangat berbeda tergantung apakah mereka:
Sebuah sumber daya adalah kata benda yang bisa diidentifikasi (mis. /users/123). Endpoint tindakan adalah kata kerja yang tertanam dalam URL (mis. /getUser, /updatePassword).
Desain berorientasi sumber daya cenderung lebih tahan lama karena pengidentifikasi tetap stabil ketika alur kerja atau UI berubah. Tindakan masih bisa ada, tetapi biasanya diekspresikan melalui metode HTTP dan representasi, bukan path berbentuk kata kerja.
Sumber daya adalah konsep ("user 123"). Representasi adalah snapshot yang Anda kirim (JSON, HTML, dll.).
Ini penting karena Anda bisa mengubah atau menambah representasi tanpa mengubah pengidentifikasi sumber daya. Klien harus bergantung pada makna sumber daya, bukan pada satu format payload tertentu.
Pemisahan client–server menjaga kepentingan tetap terpisah:
Jika sebuah keputusan memengaruhi keamanan, uang, izin, atau konsistensi bersama, itu harus berada di server. Pemisahan ini memungkinkan “satu backend, banyak frontend” (web, mobile, partner).
Stateless berarti server tidak bergantung pada status sesi klien yang disimpan untuk memahami sebuah permintaan. Setiap permintaan menyertakan informasi yang diperlukan (auth + konteks).
Manfaatnya termasuk skala horizontal yang lebih mudah (node mana pun dapat menangani permintaan) dan debugging yang lebih sederhana (konteks terlihat di log).
Pola umum:
Response yang dapat dicache memungkinkan klien atau perantara memakai kembali tanggapan sebelumnya dengan aman, mengurangi latensi dan beban server.
Alat HTTP praktis:
Cache-Control untuk kesegaran dan jangkauanAntarmuka seragam lebih dari sekadar “gunakan GET/POST/PUT/DELETE dengan benar.” Ini tentang konsistensi sehingga klien tidak memerlukan aturan khusus per-endpoint.
Fokus praktis:
Hypermedia berarti respons menyertakan tautan ke aksi berikutnya sehingga klien mengikuti tautan alih-alih meng-hardcode template URL.
Ini berguna ketika alur berubah berdasarkan status atau izin (checkout, approvals, onboarding). Tim sering melewatkannya karena menambah kerja desain (format tautan, nama relasi) — yang hilang adalah pengurangan keterikatan dan kebutuhan dokumentasi kaku.
Sistem berlapis memungkinkan perantara (CDN, gateway, proxy, layer otentikasi) sehingga klien tidak perlu tahu komponen mana yang menanggapi.
Agar lapisan tidak menyulitkan debugging:
500 generik)Lapisan adalah fitur jika sistem tetap dapat diamati dan dapat diprediksi.
Authorization: Bearer … pada setiap panggilan?cursor=... atau tautan next) alih-alih “server ingat halaman 3”ETag / Last-Modified untuk validasi (304 Not Modified)Vary ketika respons berubah berdasarkan header seperti AcceptAturan praktis: cache agresif data publik dan bersama pada GET; perlakukan data spesifik pengguna dengan hati-hati (private atau tidak dapat dicache).
200, 201 + Location, 400, 401/403, 404)code, message, details, requestId)Ini mengurangi keterikatan dan membuat perubahan kecil tidak mudah memecah klien.