Roadmap Belajar

Go dari Nol sampai Enterprise

Dari go run pertama sampai website yang melayani banyak orang di produksi โ€” dengan arsitektur yang masih bisa dipahami setelah dua tahun, keamanan yang tidak bocor, query yang tidak menghabiskan database, dan deploy tanpa jeda.

Tiga hal yang sering dicari duluan tapi jarang dibahas tuntas dibahas penuh di sini: alur lengkap satu request dari CDN sampai baris database, keamanan sistemnya, dan bagaimana persisnya semua ini di-deploy di AWS.

Durasi
~19 minggu
Beban
~8 jam/minggu
Prasyarat
Pernah ngoding, paham HTTP
Target akhir
Website enterprise di AWS

Untuk siapa roadmap ini

"Dari nol" di sini berarti nol Go, bukan nol pemrograman. Kamu diasumsikan sudah pernah menulis kode di bahasa apa pun dan paham dasar HTTP. Sintaks Go dibahas ringkas di Fase 0 dan 1 โ€” cukup untuk membaca seluruh kode di roadmap ini, tanpa berpura-pura ini kursus pemrograman dasar.

Kalau kamu belum pernah ngoding sama sekali, mulai dari Python Dasar untuk Pemula dulu. Konsepnya โ€” variabel, percabangan, fungsi, struktur data โ€” sama di semua bahasa, dan jauh lebih mudah dipelajari tanpa urusan tipe dan concurrency di atasnya.

Versi acuan: Go 1.26 (rilis Februari 2026). Beberapa hal yang dipakai di roadmap ini baru ada di rilis-rilis terakhir dan mengubah cara kode ditulis: routing bawaan ServeMux (1.22), variabel loop per iterasi (1.22), direktif tool di go.mod (1.24), GOMAXPROCS yang sadar container dan testing/synctest (1.25), serta go fix sebagai pemodernisasi kode dan Green Tea GC (1.26). Kalau sebuah tutorial menyuruhmu memasang router pihak ketiga hanya untuk mencocokkan metode HTTP, tutorial itu ditulis sebelum 2024.

Bentuk roadmap ini

BagianFaseMenjawab
Bahasanya0 โ€“ 2Cara Go mengungkapkan hal yang sudah kamu tahu โ€” termasuk concurrency
Alur satu request3 โ€“ 4Dari klien menekan Enter sampai baris database kembali
Cara menulis aplikasi nyata5 โ€“ 8Arsitektur, keamanan, framework, dan bukti bahwa semuanya masih benar
Menjalankannya untuk orang lain9 โ€“ 11Performa, AWS, dan bertahan bertahun-tahun

Urutannya disengaja. Fase 10 adalah bagian yang paling sering dicari duluan โ€” tapi deploy ke AWS tanpa tes hanya mempercepat penyebaran bug, dan menambah container di atas query N+1 hanya memindahkan masalah ke database. Jangan lompat ke Fase 10.

0

Fondasi Go & Tooling

1 minggu Go 1.26go modulesgofmtinternal/

Tujuan: punya proyek Go yang berjalan, bisa membaca kode Go tanpa tersandung sintaks, dan paham kenapa hasil go build cuma satu berkas.

Setup sekali jalan

rm -rf /usr/local/go
curl -fsSLO https://go.dev/dl/go1.26.5.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.26.5.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin

mkdir toko && cd toko
go mod init contoh.com/toko
go run .

Empat hal yang harus benar sejak hari pertama

HalKenapa
Format on save lewat goplsSetelah itu format kode tidak pernah jadi bahan review lagi
Semua kode aplikasi di internal/Satu-satunya batas modul yang ditegakkan compiler
go.mod dan go.sum di-commitgo.mod adalah berkas lock-nya
go vet ./... masuk kebiasaanIa menangkap yang lolos compiler, dan sudah ikut di go test

Materi

โœ“ Checkpoint

Kamu punya modul Go dengan cmd/ dan internal/, bisa menjelaskan apa yang dilakukan Minimal Version Selection, dan bisa membangun binari Linux dari laptopmu tanpa memasang apa pun yang berbau Linux.

1

Tipe, Interface & Error

1,5 minggu structinterfaceerrorgenerics

Tujuan: bisa merancang tipe dan interface secara idiomatik โ€” dan menulis penanganan error yang tidak kehilangan konteks maupun membocorkan detail internal.

Fase ini yang membuat sisa roadmap masuk akal. Interface implisit menjelaskan kenapa arah ketergantungan di Go bisa dibalik tanpa framework apa pun. Error sebagai nilai menjelaskan kenapa setiap jalur kegagalan terlihat di kode. Dan keduanya adalah fondasi dari arsitektur di Fase 5 dan tes di Fase 8.

Satu aturan yang menghapus banyak kebingungan: deklarasikan interface di paket yang memakainya, bukan di paket yang mengimplementasikannya โ€” dan isi hanya dengan method yang benar-benar dipanggil. Pola ini yang membuat paket domainmu tidak perlu tahu apa itu database.

Peta keputusan

KebutuhanPakaiKenapa
Method mengubah isiReceiver pointer *TReceiver nilai menerima salinan
Perilaku berbeda per tipeInterfacePolimorfisme Go datang dari sini
Algoritma sama, tipe data berbedaGenericTanpa kehilangan pemeriksaan compiler
Kegagalan yang diperkirakanerrorInput pengguna salah bukan alasan panic
Bug programmer saat startuppanicLebih baik mati sekarang daripada salah melayani
Uangint64 satuan terkecilJangan pernah float

Materi

โœ“ Checkpoint

Kamu punya paket domain dengan error sentinel yang dibungkus %w di setiap lapisan dan dipetakan jadi status HTTP di satu tempat, dan kamu bisa menjelaskan kenapa interface yang berisi pointer nil tidak sama dengan nil.

2

Concurrency

1,5 minggu goroutinechannelcontext-race

Tujuan: bisa memakai concurrency saat ia benar-benar membantu โ€” dan tahu persis kapan sebuah goroutine akan berhenti.

Yang perlu diluruskan lebih dulu: di aplikasi web, sebagian besar kodemu tidak perlu menulis concurrency sama sekali. net/http sudah menjalankan tiap permintaan di goroutine sendiri, dan pool database sudah aman dipakai bersamaan. Goroutine eksplisit dibutuhkan untuk dua hal: memanggil beberapa layanan sekaligus di dalam satu permintaan, dan pekerjaan latar.

Aturan yang menghindarkan hampir semua bug concurrency

  1. Setiap goroutine punya pemilik yang tahu kapan ia berhenti โ€” lewat WaitGroup, errgroup, atau context.
  2. Setiap goroutine berumur panjang punya recover sendiri. Satu panic di sana mematikan seluruh container.
  3. Hampir setiap select punya case <-ctx.Done().
  4. Batasi jumlahnya. "Satu goroutine per item" pada sejuta item akan menjatuhkan database duluan.
  5. go test -race di CI. Setiap laporan race adalah bug nyata.

Materi

โœ“ Checkpoint

Kamu bisa menulis fan-out ke tiga layanan dengan errgroup berikut batas paralelismenya, suite tesmu berjalan bersih dengan -race, dan kamu bisa menunjukkan kebocoran goroutine lewat profil pprof.

3

HTTP โ€” Request sampai Response

1,5 minggu net/httpServeMuxmiddlewaretimeout

Tujuan: punya server HTTP yang layak produksi, dan bisa menggambar sendiri seluruh jalur satu permintaan dari load balancer sampai handler.

Bentuk yang akan kamu tulis berulang kali

mux.HandleFunc("GET /produk/{id}", h.AmbilProduk)

func (h *Handler) AmbilProduk(w http.ResponseWriter, r *http.Request) {
	id, err := strconv.ParseInt(r.PathValue("id"), 10, 64)
	if err != nil {
		h.tulisError(w, r, ErrIDTidakValid)
		return
	}

	p, err := h.produk.Ambil(r.Context(), id)   // ctx diteruskan ke bawah
	if err != nil {
		h.tulisError(w, r, err)                  // errors.Is memetakan ke status
		return
	}

	h.tulisJSON(w, http.StatusOK, keProdukResp(p))
}

Satu baris yang tidak boleh sampai produksi: http.ListenAndServe(":8080", mux). Ia memakai server tanpa satu pun timeout, sehingga klien yang membuka koneksi lalu diam bisa menahan goroutine selamanya. Sepuluh ribu koneksi seperti itu โ€” mudah dibuat siapa saja dari satu laptop โ€” cukup untuk menjatuhkan servermu.

Empat lapis yang harus kamu bedakan

LapisTugasnyaBukan tugasnya
MiddlewareSyarat yang berlaku untuk sekelompok ruteLogika bisnis
HandlerMenerjemahkan HTTP ke domain dan sebaliknyaQuery, aturan bisnis
ServiceAturan bisnis, transaksi, cacheTahu apa itu status HTTP
RepositoryBicara ke databaseMemutuskan aturan bisnis

Materi

โœ“ Checkpoint

Servermu punya kelima timeout, rantai middleware dengan pemulih panic dan request_id, graceful shutdown yang tidak memotong permintaan berjalan, dan kamu bisa menggambar peta lengkap satu request dari CDN sampai baris database beserta anggaran waktunya.

4

Database & Persistensi

2 minggu pgxsqlctransaksiEXPLAIN

Tujuan: bisa menulis lapisan data yang aman, cepat, dan tidak menghabiskan koneksi โ€” serta mengubah skema di tabel yang sedang dipakai tanpa jeda.

Dua baris yang paling sering hilang, dan paling mahal akibatnya:

defer rows.Close()                  // tanpa ini, koneksi tidak pernah kembali
                                     // โ†’ seluruh aplikasi membeku setelah N permintaan

if err := rows.Err(); err != nil {   // tanpa ini, kegagalan di tengah pembacaan
	return nil, err                  // terlihat seperti "hasilnya memang segitu"
}

Peta keputusan

KebutuhanPakaiKenapa
Aplikasi baru, sudah pasti Postgrespgx + sqlcSQL tetap terlihat, tipenya dijaga compiler
Panel admin, CRUD membosankanGORMKecepatan menulis lebih berharga di sana
Perubahan skemaBerkas migrasiAutoMigrate tidak layak produksi
Memuat ribuan barisCopyFromSatu aliran, bukan ribuan perjalanan jaringan
Cek "sudah ada?" sebelum simpanUnique constraint + kode 23505Pemeriksaan terpisah selalu mengandung balapan
Paginasi APIKeyset, bukan OFFSETBiayanya tetap sedalam apa pun halamannya

Materi

โœ“ Checkpoint

Halaman daftarmu menjalankan jumlah kueri yang tetap berapa pun jumlah barisnya, MaxOpenConns-mu dihitung dari kapasitas database untuk jumlah task maksimum, dan kamu bisa menulis rencana tiga-deploy untuk mengganti nama kolom di tabel yang sedang dipakai.

5

Arsitektur Aplikasi

1,5 minggu lapisanDIslogantrean

Tujuan: tahu ke mana sebuah kode seharusnya diletakkan โ€” dan bisa memindahkan pekerjaan berat keluar dari siklus permintaan pengguna tanpa kehilangan pekerjaannya saat deploy.

Arah panah

cmd/server/main.go          โ† merakit semuanya (satu-satunya yang tahu segalanya)
       โ”‚
       โ–ผ
internal/http               โ† transport: parse, validasi bentuk, tulis respons
       โ”‚
       โ–ผ
internal/produk             โ† DOMAIN: tipe, aturan, interface penyimpanan
       โ–ฒ                       TIDAK tahu apa itu HTTP maupun SQL
       โ”‚
internal/produk/postgres    โ† infrastruktur: memenuhi interface domain

Uji satu kalimat yang menentukan apakah lapisanmu benar: buka blok import di paket domainmu. Kalau ada net/http atau database/sql di sana, lapisannya sudah bocor. Dan go list -deps plus linter depguard bisa menjadikan aturan ini kegagalan CI, bukan sekadar kesepakatan.

Yang tidak boleh jadi variabel global

DependensiKalau global
*sql.DB / poolTidak bisa diganti di tes; tidak ada tempat untuk Close()
LoggerTidak bisa menangkap keluaran di tes
KonfigurasiKesalahan konfigurasi jadi crash di init() tanpa konteks
time.Now"Kedaluwarsa setelah 30 hari" jadi tidak bisa diuji
Klien HTTPTidak bisa diarahkan ke httptest.Server

Materi

โœ“ Checkpoint

Nol variabel global yang bisa berubah, seluruh log membawa request_id yang sama dalam satu permintaan, pekerjaan berat sudah pindah ke antrean yang bertahan melewati restart, dan setiap job-mu aman kalau dijalankan dua kali.

6

Keamanan

2 minggu authotorisasiCSPrate limit

Tujuan: aturan "siapa boleh menyentuh apa" tinggal di satu tempat dan tidak bisa dilewati โ€” termasuk oleh orang yang mengetik ID orang lain di URL.

Pertahanan berlapis, dari yang paling lemah

LapisanCukup sendirian?
Menyembunyikan tombol di UITidak โ€” cuma urusan tampilan
Middleware per grup ruteUntuk peran, ya. Untuk objek, tidak
Pemeriksaan kebijakan di serviceYa, kalau tidak ada jalur yang melewatinya
Kueri dibatasi kepemilikanTerkuat โ€” yang bukan miliknya tidak pernah ditemukan

Yang paling sering bocor bukan autentikasi, melainkan otorisasi objek. /api/faktur/1002 yang menampilkan faktur milik orang lain, endpoint daftar yang lupa WHERE pengguna_id padahal endpoint detailnya sudah aman, atau kunci cache tanpa ID pengguna. Kelas bug ini tidak akan ditemukan tes yang cuma menguji jalur bahagia โ€” ia butuh tes dari kedua sisi.

Yang wajib dibatasi lajunya

EndpointSaranKunci
Login5 / menitemail + IP
Lupa sandi, pendaftaran3 / menitIP
Kirim OTP / SMS3 / jamnomor telepon โ€” ini biaya langsung
Pencarian30 / menitpengguna atau IP
API publik60 / menitkunci API

Materi

โœ“ Checkpoint

Setiap sumber daya punya kebijakan dengan tes dari kedua sisi, endpoint daftar terbukti tidak bocor antar pengguna, rute login dibatasi lajunya, header keamanan terpasang, dan kamu bisa menjelaskan kenapa endpoint webhook-mu memakai hmac.Equal alih-alih ==.

7

Framework Web & Frontend

1 minggu chiEchotemplhtmx

Tujuan: bisa memilih framework โ€” atau memilih tidak memakainya โ€” dengan alasan yang bisa dijelaskan, dan tahu bentuk frontend apa yang cocok untuk aplikasimu.

Di Go, pertanyaannya berbalik dari ekosistem lain. Pustaka standar sudah menutup routing, middleware, template, klien HTTP, dan testing โ€” jadi yang ditanyakan bukan "framework mana", melainkan "apa yang belum ada, dan apakah aku memerlukannya". Semua framework Go berdiri di atas http.Handler yang sama, jadi berpindah bukan penulisan ulang.

Memilih pendekatan frontend

html/templatetempl + htmxSPA + API JSON
Kesalahan template ketahuan saatRuntimeKompilasiโ€”
InteraksiMuat ulang halamanGanti sebagian halamanState di klien
Bisa di-cache penuh di CDNYaHalaman ya, fragmen tidakTidak
SEOBawaanBawaanPerlu SSR
Paling cocok untukHalaman baca publikPanel admin, form, filterAntarmuka kaya, mobile

Tidak perlu memilih satu untuk seluruh aplikasi. Pola paling sehat untuk situs bertrafik baca tinggi: halaman publik dirender server dan disajikan penuh dari CloudFront, dengan htmx hanya di bagian yang memang interaktif โ€” pencarian, filter, komentar. Panel admin boleh jadi SPA penuh; ia dipakai sedikit orang dan tidak perlu di-cache.

Materi

โœ“ Checkpoint

Kamu bisa menjelaskan kenapa memilih (atau tidak memilih) framework tertentu dalam dua kalimat, handler-mu tidak terikat tipe konteks milik framework mana pun, dan kontrak API-mu tertulis di satu tempat yang dijaga compiler.

8

Testing & Kualitas Kode

1,5 minggu testinghttptesttestcontainersgolangci-lint

Tujuan: berani men-deploy pada Jumat sore โ€” karena ada yang memeriksa selain matamu sendiri.

AlatMenangkapYang tidak bisa ditangkapnya
Tes tabelPerilaku salah pada kasus yang diujiKasus yang tidak terpikirkan
httptestKontrak HTTP, otorisasi, bentuk responsPerilaku di bawah beban
TestcontainersSQL, migrasi, constraint yang sungguhanAturan bisnis yang salah
-raceData race yang benar-benar terjadiRace di jalur yang tidak diuji
synctestGoroutine yang tidak pernah selesaiโ€”
golangci-lintBody/rows tidak ditutup, error diabaikan, batas modulKode yang jelek tapi patuh
govulncheckCVE yang bisa dijangkau kodemuKerentanan di kodemu sendiri

Yang wajib punya tes

  1. Setiap aturan otorisasi โ€” dari sisi yang boleh dan yang tidak boleh.
  2. Setiap alur yang menyentuh uang atau data pribadi.
  3. Bentuk respons setiap endpoint API publik.
  4. Setiap bug yang pernah terjadi โ€” tesnya ditulis sebelum perbaikannya.
  5. Jumlah kueri pada halaman daftar โ€” pagar terhadap N+1.
  6. Perilaku saat gagal: database mati, API luar timeout, context dibatalkan.

Cakupan 100% tidak membuktikan apa pun. Tes yang memanggil setiap fungsi tanpa memeriksa hasilnya menghasilkan cakupan penuh dan nol jaminan. Daftar enam baris di atas jauh lebih pendek โ€” dan justru di situlah kegagalan paling mahal.

Materi

โœ“ Checkpoint

CI-mu menjalankan fmt, go mod tidy, vet, lint, govulncheck, dan go test -race sebagai gerbang; ada tes yang membuktikan pengguna lain mendapat 404; dan suite lengkapnya selesai di bawah dua menit.

9

Performa & Observability

1,5 minggu pprofGOMEMLIMITRedisOpenTelemetry

Tujuan: bisa menjawab "kenapa lambat?" dengan data dalam sepuluh menit โ€” dan tahu urutan perbaikan yang benar.

Kalau lalu lintas naik, periksa dalam urutan ini

  1. Rasio hit CDN. Di bawah 90% untuk situs konten berarti ada yang salah di kunci cache โ€” biasanya query pelacakan atau cookie yang ikut masuk kunci.
  2. Kueri per permintaan. Kalau bertambah seiring jumlah baris, itu N+1.
  3. p95 database. Kueri teratas di Performance Insights biasanya menunjuk index yang hilang.
  4. Antrean pool database. WaitCount > 0 berarti setiap permintaan menghabiskan waktunya menunggu giliran.
  5. Profil CPU dan alokasi. mallocgc besar berarti terlalu banyak alokasi.
  6. Baru tambah task โ€” dan baru pikirkan arsitektur.

Pengungkit terbesar hampir selalu yang pertama. Untuk halaman yang sama bagi semua pembaca, satu header Cache-Control: public, s-maxage=300, stale-while-revalidate=3600 memindahkan sebagian besar lalu lintas ke CloudFront โ€” permintaan yang tidak pernah menyentuh proses Go, tidak pernah menyentuh database, dan tidak menambah satu pun kelas bug.

Dua variabel yang menentukan perilaku memori di Fargate

VariabelNilaiKalau tidak diset
GOMEMLIMIT~80% batas memori containerContainer di-OOM-kill tanpa satu pun log
GOMAXPROCSOtomatis sejak Go 1.25Di versi lama: throttling parah di task kecil

Materi

โœ“ Checkpoint

Kamu punya dasbor p95 per endpoint, trace yang tersambung ke log lewat trace_id, rasio hit cache yang terpantau, dan kamu pernah menemukan satu perbaikan nyata lewat flame graph pprof.

10

Deploy di AWS

2,5 minggu ECS FargateALBAuroraCloudFrontOIDC

Tujuan: git push ke main menghasilkan aplikasi baru di produksi tanpa satu pun respons non-200 selama deploy โ€” dan tanpa satu pun access key AWS tersimpan di mana pun.

Bentuk infrastrukturnya

Route 53 โ†’ CloudFront (+ WAF) โ”€โ”ฌโ”€โ†’ ALB โ†’ ECS Fargate (subnet privat)
                               โ”‚            โ”œโ”€โ”€ service server  (4 task, ALB)
                               โ”‚            โ”œโ”€โ”€ service worker  (2 task)
                               โ”‚            โ””โ”€โ”€ service cron    (1 task)
                               โ”‚                     โ”‚
                               โ””โ”€โ†’ S3 (media,        โ”œโ”€โ†’ Aurora PostgreSQL
                                      aset statis)   โ”‚     writer + reader
                                      lewat OAC      โ”œโ”€โ†’ ElastiCache Redis
                                                     โ”œโ”€โ†’ SQS
                                                     โ””โ”€โ†’ Secrets Manager

Angka yang harus selaras

SetelanNilaiHarus
ALB idle timeout60 dtk< IdleTimeout Go (65 dtk)
Deregistration delay30 dtkโ‰ฅ durasi permintaan terpanjang
stopTimeout ECS60 dtk> jeda + Shutdown + worker
GOMEMLIMIT800 MiB~80% dari memori task (1024 MB)
MaxOpenConns ร— task maks< max_connectionssisakan ruang untuk migrasi & admin

Ketidakcocokan baris pertama adalah penyebab paling umum "502 acak yang tidak ada di log aplikasi". Kalau server Go menutup koneksi keep-alive lebih dulu daripada ALB menyadarinya, ALB mengirim permintaan ke koneksi yang sedang ditutup โ€” dan permintaan itu tidak pernah sampai ke kodemu, sehingga log aplikasimu bersih total.

Materi

โœ“ Checkpoint

Deploy berjalan dari git push lewat OIDC tanpa access key, migrasi jalan sebagai task terpisah yang exit code-nya diperiksa, circuit breaker mengembalikan deploy yang gagal, rollback pernah kamu uji sungguhan, dan hey -z 120s selama deploy menghasilkan nol respons non-200.

11

Enterprise & Capstone

1,5 minggu modularmulti-tenantfeature flaggRPC

Tujuan: aplikasimu tetap bisa dipahami, diubah, dan di-upgrade setelah dua tahun dan lima orang yang berbeda menyentuhnya.

Fase-fase sebelumnya membuat aplikasi yang benar dan cepat. Fase ini tentang sifat yang baru terasa belakangan: apakah orang baru bisa menemukan kode yang dicarinya, apakah fitur bisa dimatikan tanpa deploy, apakah data satu pelanggan benar-benar terpisah dari yang lain, dan apakah kamu masih bisa naik versi tahun depan.

Materi

Capstone: portal konten bertrafik baca tinggi

Bangun satu aplikasi yang menyentuh seluruh fase. Proyek yang paling tepat adalah yang didominasi pembaca anonim dengan sedikit penulis โ€” karena bentuk beban itu memaksamu memakai hampir semua yang dipelajari di sini.

  1. Domain โ€” artikel, kategori, penulis, komentar. Tipe bernama untuk ID dan uang, error sentinel per domain.
  2. Alur request โ€” middleware lengkap, request_id di semua log, anggaran waktu berlapis dari ALB sampai kueri.
  3. Data โ€” sqlc + pgx, migrasi kompatibel dua arah, index dari EXPLAIN, keyset pagination.
  4. Redaksi โ€” alur draf โ†’ tinjau โ†’ terbit, kebijakan per peran dengan tes dari kedua sisi.
  5. Media โ€” unggahan langsung ke S3 lewat presigned URL, varian ukuran dibuat worker, disajikan lewat CloudFront.
  6. Halaman publik โ€” dirender server, tanpa JavaScript yang tidak perlu, dengan s-maxage dan stale-while-revalidate.
  7. Interaktivitas โ€” pencarian dan komentar dengan htmx; endpoint fragmen tetap punya auth dan rate limit sendiri.
  8. API โ€” kontrak OpenAPI, cursor pagination, sesi untuk web dan token untuk integrasi.
  9. Kualitas โ€” tes tabel, httptest lewat router lengkap, testcontainers, -race, golangci-lint, govulncheck โ€” semuanya gerbang CI.
  10. Performa โ€” cache Redis dengan singleflight, anggaran kueri di dalam tes, profil pprof yang pernah dibaca.
  11. Infrastruktur โ€” ECS Fargate tiga service, Aurora writer + reader, ElastiCache, SQS, Secrets Manager, CloudFront + WAF.
  12. Deploy โ€” GitHub Actions lewat OIDC, migrasi sebagai task terpisah, circuit breaker, nol respons non-200.
  13. Observability โ€” log JSON, trace tersambung ke log, delapan alarm, dasbor p95 dan rasio hit CDN.

Kenapa proyek ini: ia memaksa setiap keputusan yang dibahas di roadmap. Beban baca tinggi menuntut strategi cache berlapis; alur redaksi menuntut otorisasi yang benar; media menuntut antrean dan penyimpanan objek; dan target tanpa jeda menuntut migrasi yang kompatibel dua arah. Kalau kamu bisa menjelaskan setiap keputusan di proyek ini, kamu bisa menjalankan aplikasi Go di produksi.

โœ“ Checkpoint

Aplikasi berjalan end-to-end di AWS, di-deploy dari pipeline, punya dasbor yang menunjukkan p95 dan rasio hit CDN, batas modulnya dijaga uji arsitektur, dan kamu bisa mematikan satu fitur tanpa deploy.

Rekomendasi best practice

Ringkasan keputusan yang, kalau harus memilih satu jawaban, inilah jawabannya. Konteksnya: aplikasi Go dengan lalu lintas baca yang jauh lebih besar daripada tulis โ€” situs konten, katalog, portal. Setiap baris punya materi yang membahas alasannya.

Tumpukan yang direkomendasikan

LapisanPilihanAlasan singkat
BahasaGo 1.26Didukung sampai Feb 2027; naik tiap rilis
Routingnet/http + chiGrup middleware ringkas, tetap http.Handler
Databasepgx + sqlcSQL tetap terlihat, tipenya dijaga compiler
MigrasiBerkas SQL, di-embed ke binariSatu image berisi server dan migrasinya
Templatetempl (+ htmx untuk interaktif)Kesalahan template jadi error kompilasi
Loglog/slog, JSON ke stdoutNol dependensi; bisa dikueri di Logs Insights
ObservabilityOpenTelemetryTrace tersambung ke log lewat trace_id
Basis imagedistroless/static, non-root~17 MB, tanpa shell sama sekali
ComputeECS Fargate ARM64, tiga serviceTanpa server yang dikelola; ~20% lebih murah
Database terkelolaAurora PostgreSQL, writer + readerBeban baca pindah ke replica
Cache & sesiElastiCache RedisWajib bersama begitu ada container kedua
AntreanPostgres dulu, SQS saat volumenya besarOutbox membuatnya atomik dengan data
Aset & mediaS3 di belakang CloudFront (OAC)Bucket tidak pernah publik
Halaman publikDirender server, di-cache CloudFrontPermintaan yang tidak pernah menyentuh Go
RahasiaSecrets Manager lewat secrets ECSTidak ada rahasia di image maupun repositori
CI/CDGitHub Actions + OIDCTanpa access key jangka panjang

Sepuluh yang paling menentukan

  1. Pindahkan sebanyak mungkin ke CDN. Untuk halaman yang sama bagi semua pembaca, s-maxage plus stale-while-revalidate memangkas beban server berkali-kali lipat โ€” dan tidak menambah satu pun kelas bug. Ini pengungkit terbesar, dan yang paling sering dilewati.
  2. Batasi kueri dengan kepemilikan, bukan dengan if. WHERE id = $1 AND pengguna_id = $2 membuat data orang lain tidak pernah ditemukan โ€” pertahanan yang tidak bisa lupa dipasang.
  3. Setiap goroutine punya pemilik dan punya recover. Goroutine latar tanpa pemulih adalah penyebab container mati tanpa jejak.
  4. defer rows.Close() dan rows.Err(), selalu. Yang pertama mencegah aplikasi membeku; yang kedua mencegah data tidak lengkap yang tidak melaporkan error.
  5. Timeout di setiap lapisan, mengecil ke dalam. ALB > server > middleware > kueri. Kalau lapisan dalam lebih longgar, klien menyerah sementara kuerinya tetap memegang koneksi.
  6. Hitung MaxOpenConns untuk jumlah task maksimum. Autoscaling yang tidak memperhitungkan ini akan menjatuhkan database, bukan menyelamatkan aplikasi.
  7. Migrasi harus kompatibel dua arah. Selama rolling update, kode lama dan baru berjalan bersamaan. Ganti nama kolom = tiga deploy, bukan satu.
  8. Job harus idempoten. Ia akan berjalan dua kali โ€” worker bisa mati setelah pekerjaan selesai tapi sebelum sempat menandainya.
  9. Setel GOMEMLIMIT. Tanpa itu, container di-OOM-kill oleh kernel tanpa satu pun baris log yang menjelaskan.
  10. Ukur p95, bukan rata-rata. Rata-rata menyembunyikan satu dari sepuluh pengguna yang menunggu tiga detik.

Kesalahan yang paling mahal

KesalahanAkibatnyaDibahas di
Halaman personal ditandai public di CDNData satu pengguna tersaji ke pengguna lainFase 9, 10
Kunci cache tanpa ID pengguna atau tenantKebocoran antar pengguna / pelangganFase 6, 9, 11
rows.Close() yang hilangAplikasi membeku total setelah beberapa jamFase 4
Server tanpa ReadHeaderTimeoutSatu laptop cukup untuk menjatuhkannyaFase 3
Endpoint daftar lupa membatasi kepemilikanSemua data terlihat oleh semua orangFase 6
Decode JSON langsung ke struct domainPengguna bisa mengirim {"peran":"admin"}Fase 1
math/rand untuk token atau ID sesiSesi bisa ditebak dan dibajakFase 6
Sesi di memori dengan lebih dari satu taskPengguna ter-logout acakFase 6, 9
Image tag latestRollback tidak mengembalikan apa punFase 10
Migrasi di entrypoint container webSepuluh task menjalankannya bersamaan saat scale-outFase 4, 10
Health check ALB menyentuh databaseGangguan sebagian berubah jadi pemadaman totalFase 3, 10
IdleTimeout Go lebih kecil dari ALB502 acak tanpa jejak di log aplikasiFase 3, 10
Cron di dalam service webJob berjalan sebanyak jumlah taskFase 9, 10

Satu hal yang tidak akan diselesaikan infrastruktur: halaman yang butuh empat puluh kueri dan mengirim dua megabita HTML tetap mahal di runtime mana pun, di kelas instans apa pun, di belakang CDN mana pun. Ukur dulu, baru belanja.

Aturan main

  1. Bangun, jangan cuma baca. Hampir semua materi di sini punya latihan konkret di akhirnya; latihan itu yang membuatnya melekat.
  2. Ukur sebelum dan sesudah. Setiap klaim performa di roadmap ini bisa kamu buktikan sendiri dalam sepuluh menit โ€” lakukan.
  3. Satu perubahan pada satu waktu. Menaikkan versi Go dan menaikkan dependensi bersamaan membuat hasilnya tidak bisa dibaca.
  4. Baca pesan error sampai habis. Compiler Go termasuk yang paling jelas; sebagian besar jawabannya sudah ada di sana.
  5. Jangan lompat ke Fase 10. Godaannya besar. Deploy ke AWS tanpa tes hanya mempercepat penyebaran bug.
  6. Hapus resource AWS setelah berlatih. Aurora, ElastiCache, dan NAT Gateway ditagih per jam, dipakai atau tidak.
  7. Tulis tes untuk setiap bug. Sebelum memperbaikinya, bukan sesudah.

Sebelum & sesudah ini

Roadmap ini mengandaikan kamu sudah pernah menulis kode di bahasa apa pun dan paham dasar HTTP. Kalau belum pernah ngoding sama sekali, mulai dari Python Dasar untuk Pemula. Kalau kamu ingin mendalami sisi AWS-nya lebih jauh โ€” IAM, IaC, observability โ€” AWS untuk AI Engineer membahasnya dengan sudut pandang berbeda. Dan kalau kamu penasaran bagaimana bahasa lain menyelesaikan masalah yang sama, Laravel dari Nol sampai Enterprise menempuh jalur yang paralel dengan pertukaran yang sangat berbeda.