Biaya Microservices (2020)
(robertovitillo.com)- Backend biasanya berawal sebagai monolith, tetapi ketika beberapa tim fitur mulai menyentuh codebase yang sama, coupling dapat meningkat dan kecepatan perubahan bisa melambat
- Microservices adalah pendekatan membagi layanan berdasarkan fungsi bisnis untuk mendapatkan deployment independen dan otonomi tim kecil
- Jika layanan terlalu kecil, beban operasional menjadi lebih besar daripada manfaatnya, sehingga nama “micro” justru dapat mengaburkan penilaian
- Adopsi penuh membawa biaya luas, mulai dari standardisasi, provisioning sumber daya, pertahanan terhadap remote call, CI/CD, operasi, hingga eventual consistency
- Biasanya lebih aman memulai dari monolith, mempelajari batas-batasnya dengan cukup, lalu memisahkan satu per satu ketika growing pains membesar; pendekatan microservices-first cocok ketika ada pengalaman dan kesiapan platform
Keterbatasan yang Terlihat Saat Monolith Membesar
- Backend untuk aplikasi JavaScript single-page modern biasanya dimulai sebagai satu layanan web stateless yang menyediakan RESTful HTTP API dan menggunakan database relasional
- Layanan ini terdiri dari komponen atau library yang mengimplementasikan berbagai fungsi bisnis
- Semakin banyak tim fitur yang berkontribusi pada codebase yang sama, semakin tinggi coupling antarkomponen dan semakin mudah area kerja antartim saling tumpang tindih
- Produktivitas turun, dan cakupan dampak perubahan menjadi sulit diprediksi
- Ketika codebase sudah cukup kompleks, tidak ada orang yang benar-benar memahami keseluruhannya, sehingga implementasi fitur baru dan perbaikan bug memakan waktu lama
- Meski backend dibagi menjadi library per tim, perubahan library pada akhirnya tetap berujung pada redeployment layanan
- Jika bug seperti memory leak masuk, seluruh layanan bisa terdampak
- Jika build yang salah di-rollback, dampaknya memengaruhi kecepatan semua tim, bukan hanya tim yang membuat bug
Otonomi yang Diberikan Batas Layanan
- Salah satu cara mengurangi growing pains pada backend monolitik adalah membagi backend menjadi kumpulan layanan yang dapat di-deploy secara independen
- Layanan-layanan berkomunikasi melalui API, dan API menciptakan batas yang lebih sulit ditembus dibanding batas komponen dalam proses yang sama
- Arsitektur ini disebut arsitektur microservices, tetapi istilah
microdapat menimbulkan salah paham- Layanan tidak harus kecil
- Layanan dengan terlalu sedikit fungsi dapat menimbulkan beban operasional yang lebih besar daripada manfaatnya
- Nama yang lebih tepat mungkin service-oriented architecture, tetapi nama ini juga membawa beban lama
Kecepatan yang Dihasilkan Tim Kecil dan Layanan Independen
- Jika backend dibagi menjadi layanan berdasarkan fungsi bisnis, setiap layanan dapat dikembangkan dan dioperasikan oleh satu tim kecil
- Tim kecil lebih efektif karena biaya komunikasi meningkat secara kuadrat seiring ukuran tim
- Ketika tiap tim menentukan jadwal rilisnya sendiri dan mengendalikan codebase, koordinasi antartim berkurang dan pengambilan keputusan menjadi lebih cepat
- Jika codebase layanan kecil, developer lebih mudah memahaminya dan waktu adaptasi karyawan baru juga berkurang
- Codebase kecil juga mengurangi pelambatan IDE, sehingga membantu produktivitas developer
- Berkat batas layanan yang kuat, developer hanya perlu memahami bagian kecil, bukan keseluruhan backend, saat mengubah sebagian backend
- Setiap layanan dapat diskalakan secara independen dan dapat memilih technology stack sesuai kebutuhannya sendiri
- Konsumen API tidak peduli bagaimana fungsi diimplementasikan secara internal
- Lebih mudah bereksperimen dan mengevaluasi teknologi baru tanpa memengaruhi area sistem lain
- Setiap microservice dapat memiliki model data dan penyimpanan datanya sendiri
- Developer dapat mengubah skema tanpa memengaruhi layanan lain
Biaya Nyata yang Ditambahkan Microservices
- Microservices menambahkan lebih banyak moving parts ke seluruh sistem, dan biaya ini tidak gratis
- Biaya untuk mengadopsi microservices sepenuhnya hanya layak dibayar jika dapat diamortisasi secara terdistribusi di puluhan tim developer
-
Pengalaman Developer
- Memungkinkan setiap layanan memakai bahasa, library, dan penyimpanan data yang berbeda, tetapi hal itu dapat membuat pemeliharaan aplikasi menjadi sulit
- Jika software stack benar-benar berbeda, developer sulit berpindah dari satu tim ke tim lain
- Untuk menyediakan fitur umum yang dibutuhkan semua layanan, seperti logging, library harus didukung untuk setiap bahasa yang diadopsi
- Diperlukan tingkat standardisasi tertentu
- Pengalaman developer yang baik bagi tim yang mengikuti portofolio bahasa dan teknologi yang direkomendasikan dapat mendorong penggunaan teknologi tertentu secara longgar
-
Provisioning Sumber Daya
- Untuk mendukung banyak layanan independen, server, penyimpanan data, dan sumber daya umum lainnya harus mudah dibuat
- Setiap tim tidak boleh dibiarkan membuat cara pembuatan sumber daya sendiri-sendiri
- Sumber daya yang telah diprovisioning harus dikonfigurasi lagi, dan untuk menanganinya diperlukan otomatisasi yang cukup besar
-
Komunikasi
- Remote call mahal dan memperkenalkan cara-cara baru bagi sistem untuk runtuh
- Untuk bersiap menghadapi kegagalan, diperlukan mekanisme pertahanan seperti timeout, retry, dan circuit breaker
- Untuk mengurangi kerugian performa dari komunikasi jaringan, pemrosesan asinkron dan batching juga perlu dimanfaatkan
- Faktor-faktor ini meningkatkan kompleksitas sistem
- Monolith juga bisa mengalami masalah serupa karena akses remote client dan penggunaan API pihak ketiga, tetapi skalanya lebih kecil
-
Continuous Integration, Delivery, dan Deployment
- Continuous integration memastikan perubahan kode digabungkan ke branch utama setelah build dan test otomatis dijalankan
- Setelah perubahan kode digabungkan, perubahan itu harus dipublikasikan dan di-deploy secara otomatis ke lingkungan yang mirip production
- Di lingkungan tersebut, integration test dan end-to-end test dijalankan untuk memastikan microservice tidak merusak layanan lain yang bergantung padanya
- Pengujian microservice individual tidak lebih sulit daripada pengujian monolith, tetapi integration testing untuk semua microservice jauh lebih sulit
- Saat layanan-layanan individual berinteraksi, perilaku yang sangat halus dan tak terduga dapat muncul
-
Operasi
- Berbeda dari monolith, menempatkan tim operasi terpisah untuk setiap tim penanggung jawab layanan jauh lebih mahal
- Tim yang mengembangkan layanan biasanya juga menangani on-call untuk layanan tersebut
- Tim harus memutuskan di setiap sprint apakah akan memprioritaskan pekerjaan pengembangan atau beban operasional, dan gesekan muncul di antara keduanya
- Debugging kegagalan sistem juga menjadi lebih sulit
- Seluruh aplikasi tidak bisa dijalankan di mesin lokal dan dieksekusi langkah demi langkah dengan debugger
- Karena moving parts lebih banyak, cara kegagalan juga lebih banyak
- Logging dan monitoring yang baik di semua level menjadi penting
-
Eventual Consistency
- Jika aplikasi dibagi menjadi beberapa layanan, model data tidak lagi hanya berada dalam satu penyimpanan data
- Memperbarui record di penyimpanan data yang berbeda secara atomik dan menjamin strong consistency itu lambat, mahal, dan sulit diimplementasikan
- Arsitektur seperti ini biasanya harus menerima eventual consistency
Kapan Harus Memisahkan
- Membagi aplikasi menjadi layanan meningkatkan kompleksitas sistem secara keseluruhan secara signifikan
- Secara umum, lebih baik memulai dengan monolith dan memecahnya hanya ketika ada alasan yang cukup untuk memisahkan
- Karena menentukan batas antarlayanan dengan benar itu sulit, lebih mudah mencari titik yang tepat dengan memindahkan batas-batas di dalam monolith
- Ketika monolith sudah cukup matang dan growing pains mulai membesar, microservices dapat dipisahkan satu per satu
- Pendekatan microservices-first sebaiknya dimulai hanya jika sudah ada pengalaman, dan jika platform untuk itu sudah dibangun atau waktu yang diperlukan untuk membangun platform tersebut sudah diperhitungkan
1 komentar
Komentar Hacker News
Secara umum saya setuju dengan tulisannya, tetapi jika dilihat dari sisi lain, ada juga kasus ketika biayanya layak ditanggung: masalah kompatibilitas dependensi pihak ketiga yang sudah lama bisa dipisahkan menjadi layanan tersendiri sehingga kita dapat menghindari refactoring yang menyakitkan atau implementasi ulang sendiri; batasan deployment pada sistem inti ber-ketersediaan tinggi tidak sampai menghambat deployment sistem lain; dan batasan desain dari pelanggan besar yang tidak bisa mereka ubah dapat diisolasi.
Bukan berarti ini gratis, melainkan biaya yang layak dibayar agar tidak mengubah monolit sederhana menjadi tumpukan sampah, tidak membuatnya goyah karena deployment yang berisiko, atau tidak terikat pada mitra bisnis dengan stack teknologi yang lebih buruk.
Bukankah microservices adalah pendekatan yang pada dasarnya membuat komponen internal sebagai layanan, bukan library atau class?
Jika layanan inferensi machine learning ditulis dengan Python, UI server-side rendering dengan Rails, dan layanan yang banyak I/O serta konkurensinya dengan Go, maka beban tambahan untuk memisahkan ketiganya menjadi layanan terpisah bisa dibenarkan.
Saya cukup menyukai microservices, tetapi optimasi dini dan penskalaan dini bisa sama buruknya dengan technical debt yang muncul ketika nanti harus mengoptimalkan ke arah yang sama sekali berbeda.
Saat yang tepat untuk mengekstrak sesuatu menjadi layanan terpisah adalah ketika muncul masalah yang tidak bisa diselesaikan dengan cara yang masih dapat dikelola tanpa melakukannya.
Menambah kompleksitas arsitektur demi memaksakan batas bukanlah solusi untuk kurangnya disiplin organisasi, tetapi perusahaan teknologi skala menengah terus-menerus memperlakukannya seperti itu. Jika masalah muncul karena batas domain yang lemah, mengekstrak layanan kemungkinan besar tidak akan menyelesaikannya dengan baik.
Kutipan: https://www.oreilly.com/library/view/software-architects-han...
CI/CD yang memblokir PR sampai test lulus juga merupakan solusi teknis berbiaya besar untuk menyelesaikan masalah disiplin organisasi.
Semua orang mengakui bahwa resolusi nama domain oleh layanan eksternal itu masuk akal, dan hampir tidak ada yang mengintegrasikan recursive DNS resolver beserta cache ke dalam monolit. Namun pemisahan tanggung jawab yang sudah lama seperti ini jarang diterima sebagai contoh.
Masalahnya tampaknya adalah semakin “baik” seorang karyawan, semakin besar dorongannya untuk menunjukkan nilai, yang berujung pada over-engineering, dan akhirnya menjadi neraka.
Microservices
grug bertanya-tanya mengapa otak besar mengambil masalah tersulit, yaitu memecah sistem dengan benar, lalu masih menambahkan network call ke dalamnya.
bagi grug ini terlihat sangat membingungkan.
https://grugbrain.dev/#grug-on-microservices
“Karena SCALE_REASONS, kami ingin memodernisasi pendekatan akses FOO_TABLE dengan pindah dari MySQL ke DynamoDB, tetapi 32 dari 59 tim mengakses FOO_TABLE secara langsung atau memanggil private method class kami secara langsung. Karena prioritas mereka berbeda, tim-tim itu tidak bisa dipindahkan agar memakai FOO_SERVICE atau mengubah cara query mereka agar memakai tabel yang di-shard. Sekarang penskalaan FOO_TABLE menjadi pekerjaan beberapa kuartal, dan kami harus memberi waktu agar tim-tim bisa memperbarui secara perlahan. Dalam 1–2 tahun, mungkin kami bisa memensiunkan cara lama yang saat ini sedang terbakar. Sementara itu, selamat menikmati on-call.”
Dengan microservices, tim akan menyadari bahwa tabelnya tidak bisa diskalakan, tetapi data disediakan melalui API. Mereka merencanakan dan menjalankan migrasi pada sprint berikutnya, dan para pengguna API akan merasa semuanya menjadi jauh lebih cepat.
Jika membuka REPL Ruby modern, dari sisi autocomplete dan syntax checking Anda bisa mendapatkan banyak hal yang biasanya diharapkan dari IDE bahasa bertipe statis.
Isolasi tidak boleh dianggap enteng; itu salah satu kemampuan paling kuat yang bisa dimasukkan ke dalam software. Isolasi dapat meningkatkan performa, menciptakan batas kegagalan, dan menyediakan batas keamanan.
Ini sama dengan konsep dasar actor model. Alih-alih dua komponen saling berbagi dan mengubah memori satu sama lain, dua sistem yang terisolasi seperti actor atau microservice hanya berkomunikasi melalui protokol yang telah didefinisikan.
Saya rasa orang salah memahami modularitas. Modularitas memang penting, tetapi saya jadi berpikir ada satu prinsip arsitektur penting lain: prinsip pusaran tunggal
Dalam sistem perangkat lunak, pusaran adalah loop aliran data. Jika kita mengirim data ke suatu tempat lalu menerima kembali hasil yang sudah diproses, atau dengan cara apa pun terdampak oleh data itu, berarti ada pusaran. Variabel yang dapat diubah adalah contoh pusaran yang sangat kecil
Prinsip pusaran tunggal berarti, idealnya, sistem perangkat lunak hanya punya satu pusaran, atau dengan kata lain semua komponen harus tahu ke arah mana pusarannya berputar
Saat menggabungkan modul-modul yang membentuk dua pusaran menjadi satu, jika arah pusarannya cocok maka komposisinya mudah; jika berlawanan arah, kita harus memutuskan bagaimana arah pusaran baru, sehingga menjadi rumit. Karena itu yang terbaik adalah semua modul memiliki arah pusaran yang sama dan membentuk satu pusaran
Prinsip ini adalah generalisasi dari ide seperti pola Flux, CQRS, event sourcing, dan immutability
Atau sesuatu yang tak terduga terjadi di A sehingga C ikut terblokir. Idealnya parent hanya memanggil child dan tidak bergantung pada parent; jika gagal melakukan ini, arsitekturnya juga gagal
Saat melihat diagram arsitektur, separuh perjuangannya adalah memahami mana yang asynchronous/synchronous, push/pull, serta arah dan urutan alirannya
Enterprise service bus dan message queue tampak seperti solusi untuk membuat pusaran di tempat-tempat yang arah kedua sisinya tidak cocok
Ada bagian yang menyebut masalah “jumlah library yang harus didukung untuk menyediakan fitur umum seperti logging yang dibutuhkan semua service, satu untuk tiap bahasa yang diadopsi”
Inilah alasan terbesar kami berhenti memakai microservices. Dengan tooling tahun 2023, terutama di lingkungan cloud-native murni atau FaaS yang bisa diskalakan tanpa batas, memakai bandwidth mental untuk kekhawatiran semacam ini benar-benar sia-sia. Apalagi basis pelanggan seperti bank dan lembaga keuangan akan mengaudit tiap dependensi pihak ketiga dengan sangat ketat
Sekarang kami beroperasi dengan satu distribusi binary monolithic .NET yang sekitar 250MB jika di-gzip, dan sama sekali belum ada tanda-tanda retak. Kalau Anda sedang mengkhawatirkan dengan teliti hal-hal seperti “exe saya tidak lagi muat di L2” untuk distribusi SaaS 10–100MB, tenang saja. Perjalanan software monolithic Anda bahkan belum dimulai
Jika tiba saatnya harus menulis ulang salah satu tumpukan sampah seperti ini, bukankah jauh lebih mudah kalau semua commit berada di satu tempat yang konsisten secara global?
Microservices bukan berarti wilayah tanpa hukum, dan bukan berarti setiap tim boleh bertindak tanpa mempertimbangkan seluruh organisasi. Aturan untuk menjaga tingkat konsistensi tertentu antar-tim bisa ada dan memang seharusnya ada
Kode terbaik adalah kode yang mudah dibuang dan ditulis ulang. Dalam kenyataan, kode lama melewati lebih banyak tangan, menjadi semakin buruk, dan yang terpenting, akhirnya tidak ada yang ingin memeliharanya
Pihak yang menyukai microservices mengatakan perubahan atau penulisan ulang lebih mudah karena ada kontrak yang jelas tentang bagaimana service harus berperilaku, dan codebase service tersebut jauh lebih kecil
Pihak monolith mengatakan perubahan atau penulisan ulang lebih mudah karena semuanya adalah gulungan benang besar, jadi untuk mengubah satu helai cukup mengetahui titik-titik tempat helai itu terjalin dengan helai lain
Saya tidak tahu siapa yang benar. Monolith kemungkinan lebih baik bagi orang lama yang selama bertahun-tahun menatap codebase dengan mikroskop, sementara microservices mungkin lebih baik bagi orang lain
Dari sudut pandang release management, perpindahan dari monolith ke microservices sering dilakukan karena alasan yang keliru
Satu-satunya alasan perubahan yang benar-benar valid tampaknya adalah masalah scalability akibat bottleneck performa. Selebihnya hanya memindahkan kompleksitas pengembangan software ke pemeliharaan sistem
Tentu developer akan menyukainya karena beban besar untuk berkoordinasi dengan tim lain berkurang. Namun memperjelas kapan dan bagaimana fitur diimplementasikan, diuji dengan benar di seluruh microservices, diaktifkan di produksi, dan dikelola secara terpusat akan jauh lebih sulit jika komunikasi antar-tim pengembangan belum cukup matang. Dan ketidakmatangan itulah yang sering menjadi alasan sebenarnya monolith dipecah sejak awal
Sebaliknya, menangani banyak microservices dengan jumlah developer sedikit dan konteks yang terdefinisi baik itu menyakitkan
Pernyataan “selebihnya hanya memindahkan kompleksitas pengembangan software ke pemeliharaan sistem” masuk akal jika software sedang aktif dikembangkan. Pengembangan itu mahal. Biaya pemeliharaan sistem terdistribusi mungkin lebih rendah daripada biaya tim besar mengembangkan monolith raksasa, dan pada akhirnya semuanya tergantung situasi
Di mana tulisan “biaya monolit”? Di sini tidak terlihat. Yang terlihat hanya masalah ini karena semua orang mengimplementasikan microservice secara bodoh
Kalau semua orang mengimplementasikan monolit secara bodoh, pasti akan ada sangat banyak tulisan “monolit itu buruk”
Orang-orang tidak memahami bahwa pada akhirnya kedua sistem menghasilkan jumlah masalah yang sama. Bedanya seperti menyuruh satu gajah bekerja versus menyuruh 1000 tikus bekerja. Keduanya akan mengalami masalah, hanya saja masalahnya berbeda
Memilih salah satu tidak membuat masalah hilang. Masalah akan muncul di sisi mana pun, dan kita harus memilih salah satu lalu menyediakan solusinya. Kalau ada perusahaan yang hambatan terbesarnya adalah “arsitekturnya apa”, saya ingin bekerja di sana
Jika sebuah monolit terurai dengan baik, apa bedanya dengan microservice yang ditempatkan di lokasi yang sama? Mungkin hanya antarmukanya. Pemanggilan fungsi menjadi RPC, dan kita menerima sedikit overhead untuk mendapatkan manfaat memperlakukan komponen secara terpisah, misalnya untuk patch
Apa bedanya microservice terdistribusi dengan microservice yang berada di lokasi yang sama? Deployment lebih rumit, tetapi proses bisa ditempatkan secara cerdas pada hardware yang lebih sesuai. Mode kegagalan bertambah, tetapi kita bisa memperoleh toleransi kegagalan yang lebih tinggi
Tidak ada jawaban serba guna di sini. Jika butuh manfaatnya, bayar biayanya. Menurut saya perdebatan microservice vs monolit seperti ini muncul karena suatu pola diterapkan secara keliru, kurangnya alat yang bisa memudahkan hidup, atau sebagian besar karena software berusia 10 tahun tidak terus direfaktor dan didesain ulang sehingga menjadi menyakitkan untuk dikerjakan terlepas dari arsitektur awalnya
Ungkapan “pemanggilan fungsi menjadi RPC” terdengar sederhana, tetapi begitu itu terjadi, aplikasi klien harus menangani semua jalur eksekusi seperti server DNS tidak dapat diakses, resolusi hostname gagal, host tidak dapat dijangkau, koneksi ditolak, autentikasi ditolak, sertifikat TLS tidak tepercaya, batas laju terlampaui, 301 pindah permanen, hasil terlambat siap, dan timeout
Bahkan aplikasi yang terurai dengan baik kemungkinan besar harus didesain ulang agar bisa menangani ini secara tangguh, dengan antrean asinkron, pembatasan laju permintaan, cache hasil, retry dengan backoff log, kredensial klien・trust store・URL resource yang dapat dikonfigurasi, serta logging kegagalan
Pada pemanggilan fungsi lokal, fungsi RPC dan parameter tambahan juga diperlukan untuk menyediakan data yang sebelumnya ada dalam konteks. Selain itu, UI monolit mungkin perlu menyampaikan latensi dan kegagalan jaringan kepada pengguna, sesuatu yang sebelumnya tidak mungkin terjadi
Bahkan monolit yang dibuat paling baik pun membutuhkan upaya besar untuk direfaktor menjadi microservice
Apakah panggilan RPC ini bisa di-retry dengan aman? Bagaimana dengan exponential backoff? Apakah API load balancer bekerja dengan benar? Kalau begitu monitoring juga diperlukan. Bagaimana melakukan tracing antar-microservice? Sekarang kita memerlukan sesuatu seperti OpenTelemetry
Seberapa jauh lebih sulit debugging dengan breakpoint dalam arsitektur microservice? Bagaimana membatalkan transaksi database di antara dua microservice? Pemanggilan fungsi sederhana tiba-tiba menjadi jauh lebih kompleks
Setiap kali membela konsep ini, mereka mengabaikan fragmentasi yang ditimbulkan oleh tuntutan bahwa service harus sangat kecil. Lebih spesifiknya, jika ada satu monolit dan satu microservice, itu bukan microservice-microservice. Istilah microservice menyiratkan bahwa semuanya dipecah menjadi service kecil dan tidak ada monolit
Sebagian besar argumen pro-microservice runtuh begitu menyadari bahwa ia harus benar-benar “micro”. Dan jika tuntutan itu ditinggalkan, tidak ada usulan baru atau mendalam yang tersisa
Dari sudut pandang operasi, mengatakan “deployment lebih rumit” adalah pernyataan yang sangat mengecilkan masalah. Setiap paket adalah objek yang harus dikelola secara terpisah, dengan karakteristik dan masalahnya sendiri
Mirip dengan developer frontend yang berpikir mereka tidak bisa membuat “aplikasi web modern” tanpa framework atau library frontend seperti React/Vue/Svelte, sekarang tampaknya ada anggapan bahwa “monolit” sama dengan menjalankan satu bongkahan tar raksasa yang menakutkan sebagai satu instance sehingga “tidak bisa diskalakan”, dan ini tidak masuk akal
Hal lain yang terlihat adalah jumlah kode keseluruhan menjadi jauh lebih besar, dan sebagian besar service terdiri dari 20% kode bisnis/domain dan 80% penanganan pengiriman dan penerimaan pesan jaringan. Sebaik apa pun disembunyikan, pada akhirnya itu tetap ada, dan jaringan harus ditangani dengan suatu cara
Sama seperti kegilaan frontend, kultus microservice ini baru akan berakhir ketika ekonomi runtuh dan tidak ada lagi uang untuk menopang menara Babel menuju kehancuran seperti ini
Sebagai tambahan, microservice juga punya tempat penggunaannya. Di sebagian perusahaan yang mendapatkan nilai lebih besar daripada biayanya, itu memang tepat
Ada juga manfaat teknis seperti penskalaan independen per service, tetapi manfaat terbesarnya adalah batas kepemilikan yang jelas dan mencegah coupling berlebihan yang tidak perlu
Jika tim kecil membuat satu produk, kemungkinan besar belum ada masalah organisasi yang dipecahkan oleh microservice, jadi mungkin tidak diperlukan. Dalam kasus itu, microservice adalah optimasi prematur, artinya membayar biaya untuk menyelesaikan masalah yang belum ada
Lebih jauh lagi, kompleksitas frontend semuanya ada di kepala: https://bower.sh/front-end-complexity
Tulisan ini tampaknya berangkat dari premis bahwa organisasi pengembangan sudah benar-benar rusak dan di luar kendali. Mereka tidak bisa menentukan apa yang akan dikerjakan selama sprint, diam-diam memasukkan library pihak ketiga dan bahasa yang tidak dikenal, lalu diam-diam menerapkan perubahan yang tidak kompatibel ke produksi
Kalau para developer bukan orang bodoh, microservices juga rasanya akan lebih mudah
Saya yakin microservices akan lebih mudah jika bekerja di tim yang terdiri dari developer yang cerdas dan kompeten. Tentu saja, kalau begitu semuanya juga akan jadi lebih mudah