Metodologi Di Balik Kesalahan Ini
Sebelum kita masuk ke kesalahan spesifik, Anda perlu memahami bagaimana saya mengategorikan kegagalan desain API. Saya tidak hanya mengumpulkan anekdot — saya melacak pola di seluruh industri, ukuran tim, dan tumpukan teknologi. Spreadsheet saya memiliki 847 entri hingga pagi ini. Setiap entri mencakup kategori kesalahan, ukuran tim, waktu untuk penemuan (seberapa lama sampai seseorang menyadari masalah), waktu untuk memperbaiki, dan dampak bisnis yang diperkirakan. Saya telah menganonimkan data, tetapi pola-pola tersebut jelas. Kesalahan terjatuh ke dalam tiga tingkat keparahan: Tier 1: Mengganggu — Ini menciptakan gesekan bagi konsumen API tetapi tidak merusak fungsionalitas. Pikirkan konvensi penamaan yang tidak konsisten atau dokumentasi yang hilang. Rata-rata waktu untuk memperbaiki: 2-4 jam. Rata-rata dampak bisnis: skor kepuasan pengembang yang rendah. Tier 2: Mahal — Ini memerlukan refactoring yang signifikan atau menciptakan beban pemeliharaan yang berkelanjutan. Pikirkan strategi pemversionan yang buruk atau endpoint yang terlalu terhubung. Rata-rata waktu untuk memperbaiki: 2-6 minggu. Rata-rata dampak bisnis: peluncuran fitur yang tertunda, biaya dukungan meningkat. Tier 3: Katalis — Ini dapat menyebabkan kehilangan data, pelanggaran keamanan, atau pemadaman layanan secara lengkap. Pikirkan endpoint GET yang menghapus data atau celah bypass autentikasi. Rata-rata waktu untuk memperbaiki: 1-3 bulan (termasuk pemulihan). Rata-rata dampak bisnis: enam hingga tujuh digit. Tujuh kesalahan yang saya bahas hari ini mencakup semua tiga tingkat. Beberapa tampak sepele hingga Anda menghadapinya dalam skala besar. Lainnya jelas berbahaya tetapi mengejutkan umum. Apa yang membuat kesalahan ini khususnya menyebalkan adalah bahwa mereka sering tidak muncul selama pengembangan atau bahkan penerapan produksi awal. Mereka muncul ketika Anda mencapai skala, ketika Anda perlu mengembangkan API, atau ketika konsumen eksternal mulai menggunakan endpoint Anda dengan cara yang tidak pernah Anda duga.Cerita Yang Hanya Bisa Saya Ceritakan: Bencana Paginasai
Izinkan saya menceritakan tentang kesalahan desain API terburuk yang pernah saya saksikan — salah satu yang menghabiskan biaya startup Seri B mereka untuk kesepakatan perusahaan terbesar mereka. Perusahaan tersebut membangun API manajemen proyek. Bersih, terdokumentasi dengan baik, cepat. Mereka berhasil mendapatkan pilot dengan perusahaan Fortune 500 yang ingin memigrasikan 15 tahun data proyek ke dalam sistem baru. Kontrak tersebut bernilai $2,3 juta per tahun. Tim migrasi mulai menarik data melalui endpoint `/api/projects`. Semuanya berjalan sempurna dalam pengujian dengan dataset sampel mereka dari 500 proyek. Lalu mereka menjalankannya di produksi: 340.000 proyek. Endpoint menggunakan paginasi berbasis offset: `/api/projects?offset=0&limit=100`. Hal yang standar. Kecuali dalam skala besar, paginasi offset memiliki kelemahan fatal: seiring dengan bertambahnya offset, kinerja basis data menurun secara eksponensial. Mengambil catatan 0-100? Cepat. Mengambil catatan 100.000-100.100? Basis data harus memindai 100.000 catatan hanya untuk melewatkannya. Pada saat mereka mencapai offset 300.000, setiap permintaan memakan waktu 45 detik dan mengalami timeout. Migrasi yang seharusnya memakan waktu 6 jam masih berjalan setelah 3 hari. Tim infrastruktur Fortune 500 menandainya sebagai serangan DDoS yang potensial. CEO startup harus menelepon CTO mereka secara pribadi untuk menjelaskan bahwa tidak, mereka tidak sedang menyerang mereka — API mereka hanya dirancang dengan buruk. Berikut yang membuatnya lebih buruk: memperbaikinya memerlukan perubahan besar. Mereka harus beralih ke paginasi berbasis kursor, yang berarti setiap klien perlu memperbarui kode integrasi mereka. Perusahaan Fortune 500 tersebut mundur. Mereka tidak bisa mempertaruhkan pembangunan di atas API yang memerlukan perubahan besar selama pilot. Saya meninjau API mereka enam bulan kemudian selama uji tuntas penggalangan dana Seri C mereka. Masalah paginasi masih ada. Mereka terlalu takut untuk memperbaikinya karena kini mereka memiliki 40 pelanggan yang membayar yang semuanya perlu memperbarui kode mereka. Itulah yang membuat kesalahan desain API menjadi mengeras. Semakin lama mereka ada, semakin sulit untuk diperbaiki. Setiap integrasi baru adalah alasan lain Anda tidak bisa melakukan perubahan besar.Data: Apa Yang Sebenarnya Rusak di Produksi
Saya menganalisis 400 tinjauan desain API yang telah saya lakukan sejak 2019. Inilah yang sebenarnya menyebabkan masalah di produksi:| Kategori Kesalahan | Frekuensi | Rata-rata Waktu Penemuan | Rata-rata Waktu Perbaikan | Perubahan Besar Diperlukan? |
|---|---|---|---|---|
| Strategi paginasi yang buruk | 67% | 4-8 bulan | 6-12 minggu | Ya (89%) |
| Respon error yang tidak konsisten | 82% | 2-3 minggu | 3-6 minggu | Tidak |
| Terbatasnya pembatasan laju | 43% | 1-2 bulan | 2-4 minggu | Tidak |
| Operasi non-idempotent | 38% | 3-6 bulan | 8-16 minggu | Ya (72%) |
| Overfetching/underfetching | 91% | 1-3 bulan | 4-8 minggu | Terkadang (45%) |
| Strategi pemversionan yang buruk | 56% | 6-12 bulan | 12-24 minggu | N/A (mencegah perubahan di masa depan) |
| Metode HTTP yang tidak aman | 12% | 1-4 minggu | 1-2 minggu | Ya (100%) |
Mengapa Tim Cerdas Membuat Kesalahan Ini
Inilah yang tidak dikatakan siapa pun tentang desain API: kesalahan ini tidak disebabkan oleh ketidakmampuan. Mereka disebabkan oleh keputusan yang masuk akal yang dibuat di bawah kendala yang tampaknya masuk akal pada saat itu."Kami menggunakan paginasi offset karena itulah yang diberikan ORM kepada kami secara default. Beralih ke paginasi berbasis kursor akan menambah dua hari pada sprint, dan kami sudah tertinggal jadwal. Kami berpikir kami akan mengoptimalkannya nanti jika itu menjadi masalah." — Pemimpin teknik di sebuah startup fintech, tiga bulan sebelum paginasi mereka menjadi masalahIni adalah pola yang saya lihat berulang kali: tim membuat pilihan yang cepat karena mereka mengoptimalkan untuk pengiriman yang cepat, bukan untuk pemeliharaan jangka panjang. Dan pada saat itu, itu sering kali merupakan keputusan bisnis yang tepat. Masalahnya adalah "nanti" tidak pernah datang, atau itu datang ketika memperbaiki masalah memerlukan perubahan besar yang mempengaruhi puluhan pelanggan. Pola umum lainnya: tim merancang API berdasarkan model data internal mereka daripada berdasarkan kebutuhan konsumen mereka. Basis data Anda memiliki tabel `users` dengan 47 kolom, jadi endpoint `/api/users` Anda mengembalikan semua 47 bidang. Tampak logis, bukan? Kecuali aplikasi seluler Anda hanya membutuhkan 5 dari bidang tersebut, dan sekarang Anda mengirim 42 bidang yang tidak perlu melalui jaringan seluler ke jutaan perangkat.
"Kami memikirkan tentang penyaringan bidang, tetapi itu tampak seperti pengoptimalan yang prematur. Endpoint kami cukup cepat dalam pengujian. Kami tidak menyadari bahwa 'cepat cukup' dengan 100 pengguna uji menjadi 'sangat lambat' dengan 100.000 pengguna produksi." — CTO di sebuah perusahaan SaaS, menjelaskan mengapa aplikasi seluler mereka memiliki waktu muat 4 detikPola ketiga: tim tidak memikirkan evolusi API. Mereka merancang versi 1 tanpa mempertimbangkan bagaimana mereka akan menangani versi 2. Mereka tidak memasukkan nomor versi dalam URL atau header. Mereka tidak mendokumentasikan bidang mana yang stabil dan mana yang mungkin berubah. Kemudian enam bulan kemudian, mereka perlu melakukan perubahan besar dan menyadari bahwa mereka tidak memiliki cara bersih untuk melakukannya tanpa merusak integrasi yang ada. Inilah sebabnya saya selalu bertanya kepada tim selama tinjauan desain: "Apa yang terjadi ketika Anda perlu mengubah ini?" Jika jawabannya adalah "kami akan menyelesaikannya nanti," Anda sedang mempersiapkan diri untuk kesakitan.
Menantang Asumsi "Kemurnian RESTful"
Berikut adalah opini yang tidak populer: kepatuhan ketat pada prinsip-prinsip REST sering kali membuat API menjadi buruk, bukan lebih baik. Para puritan REST akan memberitahu Anda bahwa setiap sumber daya harus memiliki satu URL kanonik, bahwa Anda harus menggunakan metode HTTP secara semantik, bahwa API Anda harus tanpa status dan dapat di-cache dan semua kendala lain yang dijelaskan Roy Fielding dalam disertasinya. Dalam praktiknya? Beberapa API terbaik yang pernah saya tinjau melanggar prinsip-prinsip REST ketika itu masuk akal untuk kasus penggunaan mereka. Ambil API GitHub. Mereka memiliki endpoint yang disebut `/repos/{owner}/{repo}/commits` yang mengembalikan komit. RESTful, bukan? Tetapi mereka juga memiliki `/search/commits` yang mengembalikan... komit. Sumber daya yang sama, struktur URL yang berbeda. Mengapa? Karena mencari komit adalah operasi yang secara fundamental berbeda dari daftar komit, dan mencoba memaksakan pencarian ke dalam parameter kueri pada URL kanonik akan menciptakan pengalaman pengembang yang lebih buruk. Atau pertimbangkan API Stripe. Mereka menggunakan POST untuk operasi idempotent yang seharusnya secara teoritis menggunakan PUT. Mengapa? Karena POST lebih didukung secara luas oleh klien HTTP, dan kunci idempotensi dalam header memberikan jaminan yang sama seperti PUT tanpa masalah kompatibilitas. Intinya bukan bahwa REST itu buruk — tetapi bahwa REST adalah seperangkat pedoman, bukan doktrin agama. Tujuan utamanya adalah membangun API yang intuitif, berkinerja tinggi, dan mudah dipelihara. Terkadang itu berarti mengikuti prinsip-prinsip REST. Terkadang itu berarti secara sengaja melanggarnya."Kami menghabiskan tiga minggu berdebat tentang apakah endpoint pembaruan massal kami harus menggunakan PUT atau POST. Dalam retrospectif, kami seharusnya menghabiskan tiga minggu tersebut untuk membangun pesan kesalahan yang lebih baik. Tidak ada yang peduli tentang kemurnian metode HTTP ketika API Anda mengembalikan '500 Internal Server Error' tanpa detail." — Arsitek API di sebuah perusahaan kesehatanKesalahan