6 menit

Penyimpanan objek vs blob di database untuk unggahan cepat dan murah

Penyimpanan objek vs blob database: simpan metadata file di Postgres, simpan byte di object storage, dan jaga unduhan cepat dengan biaya yang dapat diprediksi.

Penyimpanan objek vs blob di database untuk unggahan cepat dan murah

Masalah nyata dengan unggahan pengguna

Unggahan pengguna terdengar sederhana: terima file, simpan, tampilkan nanti. Itu bekerja dengan beberapa pengguna dan file kecil. Lalu volume bertambah, file semakin besar, dan rasa sakit muncul di tempat yang tidak ada hubungannya dengan tombol unggah.

Unduhan melambat karena server aplikasi atau database melakukan pekerjaan berat. Backup menjadi besar dan lambat, sehingga restore memakan waktu lebih lama tepat saat Anda membutuhkannya. Tagihan penyimpanan dan bandwidth (egress) bisa melonjak karena file disajikan secara tidak efisien, terduplikasi, atau tidak pernah dibersihkan.

Yang biasanya Anda inginkan adalah hal yang membosankan namun andal: transfer cepat di bawah beban, aturan akses yang jelas, operasi sederhana (backup, restore, pembersihan), dan biaya yang tetap dapat diprediksi seiring pertumbuhan penggunaan.

Untuk sampai di sana, pisahkan dua hal yang sering tercampur:

Metadata adalah informasi kecil tentang file: siapa pemiliknya, bagaimana namanya, ukuran, tipe, kapan diunggah, dan di mana ia berada. Ini milik database Anda (seperti Postgres) karena Anda perlu melakukan query, filter, dan join ke pengguna, proyek, dan permission.

Byte file adalah isi aktual file (foto, PDF, video). Menyimpan byte di dalam blob database bisa bekerja, tetapi membuat database lebih berat, backup lebih besar, dan performa lebih sulit diprediksi. Menaruh byte di object storage menjaga database tetap fokus pada hal yang dilakukannya dengan baik, sementara file disajikan cepat dan murah oleh sistem yang dibuat untuk itu.

Penyimpanan objek vs blob di database, dalam istilah sederhana

Saat orang bilang "simpan unggahan di database," mereka biasanya maksudnya blob database: entah kolom BYTEA (byte mentah dalam baris) atau Postgres "large objects" (fitur yang menyimpan nilai besar secara terpisah). Keduanya bisa bekerja, tapi keduanya membuat database Anda bertanggung jawab untuk menyajikan byte file.

Object storage adalah ide berbeda: file tinggal di bucket sebagai object, diakses dengan key (mis. uploads/2026/01/file.pdf). Ini dibuat untuk file besar, penyimpanan murah, dan unduhan streaming. Sistem ini juga menangani banyak pembacaan konkuren dengan baik, tanpa mengikat koneksi database Anda.

Postgres bersinar pada query, constraint, dan transaksi. Ia cocok untuk metadata seperti siapa pemilik file, apa isi file, kapan diunggah, dan apakah file bisa diunduh. Metadata itu kecil, mudah diindeks, dan mudah dijaga konsistensinya.

Aturan praktis singkat:

  • Gunakan Postgres untuk metadata file, permission, dan relasi.
  • Gunakan object storage untuk byte saat file bisa tumbuh melebihi beberapa MB, atau saat unduhan sering terjadi.
  • Pertimbangkan blob DB hanya untuk aset kecil yang harus terikat secara transaksional ke sebuah record (mis. ikon kecil), dan Anda yakin pertumbuhan database akan tetap moderat.

Pemeriksaan akal sehat cepat: jika backup, replica, dan migrasi akan menjadi menyusahkan jika byte file disertakan, jangan simpan byte di Postgres.

Arsitektur sederhana yang tetap mudah dikelola

Setup yang biasanya dipakai tim cukup sederhana: simpan byte di object storage, dan simpan record file (siapa pemiliknya, apa itu, di mana lokasinya) di Postgres. API Anda mengoordinasikan dan mengotorisasi, tapi tidak menjadi proxy untuk unggahan dan unduhan besar.

Itu membagi tiga tanggung jawab dengan jelas:

  • Postgres menyimpan satu baris kecil per file: file_id yang stabil, pemilik, ukuran, content type, dan pointer ke object.
  • Object storage menyimpan byte aktual, dioptimalkan untuk file besar dan penyimpanan murah.
  • API Anda membuat dan mengotorisasi record file, serta mengeluarkan izin berumur pendek ke storage.

file_id yang stabil itu menjadi primary key untuk segalanya: komentar yang merujuk lampiran, invoice yang menunjuk PDF, log audit, dan alat dukungan. Pengguna bisa mengganti nama file, Anda bisa memindahkannya antar bucket, dan file_id tetap sama.

Jika memungkinkan, anggap object yang disimpan bersifat immutable. Jika pengguna mengganti dokumen, buat object baru (dan biasanya baris baru atau baris versi baru) daripada menimpa byte di tempat. Ini menyederhanakan caching, menghindari kejutan "tautan lama menampilkan file baru", dan memberi alur rollback yang bersih.

Putuskan privasi sejak dini: privat secara default, publik hanya jika perlu. Aturan yang baik adalah: database adalah sumber kebenaran untuk siapa yang dapat mengakses file; object storage menegakkan izin berumur pendek yang dikeluarkan API Anda.

Cara memodelkan metadata file di Postgres

Dengan pemisahan bersih, Postgres menyimpan fakta tentang file, dan object storage menyimpan byte. Itu menjaga database lebih kecil, backup lebih cepat, dan query sederhana.

Tabel uploads praktis hanya membutuhkan beberapa field untuk menjawab pertanyaan nyata seperti "siapa pemilik ini?", "di mana disimpan?", dan "aman untuk diunduh?"

CREATE TABLE uploads (
  id               uuid PRIMARY KEY,
  owner_id         uuid NOT NULL,
  bucket           text NOT NULL,
  object_key       text NOT NULL,
  size_bytes       bigint NOT NULL,
  content_type     text,
  original_filename text,
  checksum         text,
  state            text NOT NULL CHECK (state IN ('pending','uploaded','failed','deleted')),
  created_at       timestamptz NOT NULL DEFAULT now()
);

CREATE INDEX uploads_owner_created_idx ON uploads (owner_id, created_at DESC);
CREATE INDEX uploads_checksum_idx ON uploads (checksum);

Beberapa keputusan yang menghemat rasa sakit nanti:

  • Gunakan bucket + object_key sebagai pointer storage. Jaga agar tidak berubah setelah diunggah.
  • Lacak state. Ketika pengguna memulai unggahan, masukkan baris pending. Ganti ke uploaded hanya setelah sistem Anda mengonfirmasi object ada dan ukurannya (dan idealnya checksum) cocok.
  • Simpan original_filename hanya untuk ditampilkan. Jangan mengandalkannya untuk keputusan tipe atau keamanan.

Jika Anda mendukung penggantian (mis. pengguna mengunggah ulang invoice), tambahkan tabel upload_versions terpisah dengan upload_id, version, object_key, dan created_at. Dengan begitu Anda bisa menyimpan riwayat, rollback kesalahan, dan menghindari merusak referensi lama.

Alur unggah langkah demi langkah (tanpa memblokir API Anda)

Jaga unggahan tetap cepat dengan membuat API menangani koordinasi, bukan byte file. Database Anda tetap responsif, sementara object storage menanggung beban bandwidth.

Mulailah dengan membuat record unggahan sebelum file dikirim. API Anda mengembalikan upload_id, di mana file akan disimpan (object_key), dan izin unggah berumur pendek.

Alur umum:

  1. Klien meminta mengunggah: API membuat baris dengan pending, plus ukuran yang diharapkan dan content type yang dimaksudkan.
  2. API mengembalikan presigned URL: untuk file besar, hasilkan presigned upload URL. Untuk file kecil (mis. avatar), Anda tetap bisa memproxy lewat backend jika ingin kode klien lebih sederhana.
  3. Klien mengunggah langsung ke object storage: browser atau aplikasi mobile mengirim byte ke storage, bukan lewat API Anda.
  4. Finalize: klien memanggil API Anda dengan upload_id dan field respons storage (mis. ETag). Server Anda memverifikasi ukuran, checksum (jika dipakai), dan content type, lalu menandai baris uploaded.
  5. Gagal dengan aman: jika verifikasi gagal, tandai failed dan opsional hapus object.

Retry dan duplikat itu normal. Buat panggilan finalize idempoten: jika upload_id yang sama difinalisasi dua kali, kembalikan sukses tanpa mengubah apa pun.

Untuk mengurangi duplikat akibat retry dan re-upload, simpan checksum dan anggap "pemilik sama + checksum sama + ukuran sama" sebagai file yang sama.

Alur unduh langkah demi langkah (cepat dan ramah cache)

Kirim unduhan privat
Tambahkan endpoint gate file_id stabil dan keluarkan akses unduh berumur pendek.

Alur unduh yang baik dimulai dengan satu URL stabil di aplikasi Anda, meski byte berada di tempat lain. Pikirkan: /files/{file_id}. API Anda menggunakan file_id untuk mencari metadata di Postgres, memeriksa izin, lalu memutuskan cara mengirim file.

  1. Klien meminta URL stabil Anda dengan file_id.
  2. API memverifikasi pengguna dapat mengaksesnya dan file berstatus uploaded.
  3. API mengembalikan redirect ke object storage (seringkali terbaik), atau presigned GET URL berumur pendek untuk file privat.
  4. Klien mengunduh langsung dari object storage, menjaga API dan server aplikasi Anda keluar dari jalur panas.

Redirect sederhana dan cepat untuk file publik atau semi-publik. Untuk file privat, presigned GET URL menjaga storage tetap privat sekaligus memungkinkan browser mengunduh langsung.

Untuk video dan unduhan besar, pastikan object storage (dan lapisan proxy apa pun) mendukung range request (Range headers). Ini memungkinkan seeking dan unduhan yang dapat dilanjutkan. Jika Anda memproses byte lewat API, dukungan range sering rusak atau menjadi mahal.

Caching adalah sumber kecepatan. Endpoint stabil /files/{file_id} biasanya tidak bisa di-cache (ini gerbang otentikasi), sementara respons object storage sering bisa di-cache berdasarkan konten. Jika file immutable (unggahan baru = key baru), Anda bisa mengatur lifetime cache panjang. Jika menimpa file, jaga waktu cache pendek atau gunakan key yang versioned.

CDN membantu saat Anda punya banyak pengguna global atau file besar. Jika audiens kecil atau kebanyakan di satu region, object storage saja sering cukup dan lebih murah untuk memulai.

Menjaga biaya tetap dapat diprediksi seiring waktu

Tagihan kejutan biasanya datang dari unduhan dan churn, bukan byte mentah yang ada di disk.

Hitung empat penggerak yang mengubah angka: berapa banyak yang Anda simpan, seberapa sering Anda baca dan tulis (request), berapa banyak data keluar dari provider Anda (egress), dan apakah Anda memakai CDN untuk mengurangi unduhan ulang dari origin. File kecil yang diunduh 10.000 kali bisa lebih mahal daripada file besar yang tidak pernah disentuh.

Kontrol yang menjaga pengeluaran stabil:

  • Batasi ukuran file per unggahan dan tetapkan kuota per pengguna berdasarkan paket.
  • Rate limit unggahan dan unduhan untuk mencegah penyalahgunaan dan loop tak sengaja.
  • Gunakan aturan lifecycle sehingga file lama pindah ke kelas yang lebih murah, atau kadaluarsa saat tidak lagi diperlukan.
  • Deduplikasi berdasarkan checksum sehingga retry atau re-upload tidak membuat salinan ekstra.
  • Simpan counter penggunaan di Postgres sehingga penagihan dan peringatan berbasis fakta, bukan tebakan.

Aturan lifecycle sering kali kemenangan termudah. Contoh: simpan foto asli "hot" selama 30 hari, lalu pindahkan ke kelas storage yang lebih murah; simpan invoice selama 7 tahun, tapi hapus bagian upload yang gagal setelah 7 hari. Kebijakan retensi dasar saja menghentikan pertumbuhan penyimpanan yang tak terkendali.

Deduplikasi bisa sederhana: simpan hash konten (mis. SHA-256) di tabel metadata file dan tegakkan unik per pemilik. Saat pengguna mengunggah PDF yang sama dua kali, Anda bisa memakai object yang ada dan hanya membuat baris metadata baru.

Terakhir, lacak penggunaan di tempat Anda sudah melakukan akuntansi pengguna: Postgres. Simpan bytes_uploaded, bytes_downloaded, object_count, dan last_activity_at per pengguna atau workspace. Itu memudahkan menampilkan batas di UI dan memicu peringatan sebelum tagihan datang.

Dasar keamanan dan kepatuhan untuk unggahan

Dari lokal ke live
Deploy dan hosting aplikasi yang dihasilkan sehingga unggahan dan unduhan dapat diuji secara end-to-end.

Keamanan unggahan berfokus pada dua hal: siapa yang dapat mengakses file, dan apa yang bisa Anda buktikan nanti jika terjadi masalah.

Kontrol akses yang sesuai kebutuhan nyata

Mulai dengan model akses yang jelas dan enkode di metadata Postgres, bukan aturan satu-off yang berserak di layanan.

Model sederhana yang menutup kebanyakan aplikasi:

  • Owner-only: hanya pengunggah (dan admin) yang dapat mengakses.
  • Shared: dapat diakses oleh pengguna tertentu atau tim/workspace.
  • Public: dapat diakses tanpa login (pakai hemat, dan tetap lacak).

Untuk file privat, hindari mengekspos object key mentah. Keluarkan URL unggah dan unduh berumur pendek yang dibatasi scope, dan rotasi secara sering.

Pemeriksaan kepatuhan yang menyelamatkan nanti

Verifikasi enkripsi baik saat transit maupun saat disimpan. In transit berarti HTTPS end-to-end, termasuk unggahan langsung ke storage. At rest berarti enkripsi sisi server di penyedia storage Anda, dan bahwa backup serta replica juga terenkripsi.

Tambahkan titik pemeriksaan untuk keselamatan dan kualitas data: validasi content type dan ukuran sebelum mengeluarkan upload URL, lalu validasi lagi setelah unggah (berdasarkan byte yang tersimpan, bukan hanya nama file). Jika profil risiko Anda membutuhkannya, jalankan scanning malware secara asinkron dan karantina file sampai lulus.

Simpan field audit agar Anda bisa menyelidiki insiden dan memenuhi kebutuhan kepatuhan dasar: uploaded_by, ip, user_agent, dan last_accessed_at adalah baseline yang praktis.

Jika Anda punya persyaratan residensi data, pilih region storage dengan sengaja dan jaga konsistensinya dengan tempat compute berjalan.

Kesalahan umum yang menyebabkan perlambatan dan insiden

Kebanyakan masalah unggahan bukan soal kecepatan mentah. Mereka datang dari pilihan desain yang terasa nyaman di awal, lalu menyakitkan ketika Anda punya trafik nyata, data nyata, dan tiket dukungan nyata.

  • Menyimpan byte file di dalam Postgres: Bekerja untuk aplikasi kecil, lalu backup membengkak, restore memakan waktu lama, dan pemeliharaan rutin menjadi berisiko. Satu tabel besar bisa memperlambat vacuum, replikasi, dan bahkan query sederhana.
  • Menggunakan nama file dari pengguna sebagai object key: Tabrakan terjadi (dua pengguna mengunggah "invoice.pdf"), dan karakter aneh menciptakan edge case. Simpan nama file untuk ditampilkan, tapi hasilkan key unik (seperti UUID) untuk penyimpanan.
  • Melewatkan validasi saat finalize: Bahkan jika Anda memvalidasi di klien, Anda tetap perlu pengecekan sisi server untuk ukuran, content type, dan kepemilikan saat menandai unggahan selesai.
  • Membuat object publik secara tidak sengaja dan tidak pernah merotasi akses: Kebijakan bucket publik "sementara" atau URL jangka panjang sering menjadi permanen. Lebih baik link unduh berumur pendek, dan punya cara untuk mencabut akses dengan cepat.
  • Menghapus hanya satu sisi (metadata atau byte): Menghapus baris Postgres tapi membiarkan object akan menimbulkan kebocoran biaya diam-diam. Menghapus object tapi menyimpan metadata menciptakan unduhan rusak dan beban dukungan.

Contoh konkret: jika pengguna mengganti foto profil tiga kali, Anda bisa berakhir membayar untuk tiga object lama selamanya kecuali Anda menjadwalkan pembersihan. Pola aman adalah soft delete di Postgres, lalu job background yang menghapus object dan merekam hasilnya.

Daftar periksa cepat sebelum peluncuran

Sebagian besar masalah muncul ketika file besar pertama tiba, pengguna me-refresh di tengah unggah, atau seseorang menghapus akun dan byte tetap ada.

Pastikan tabel Postgres Anda merekam ukuran file, checksum (agar Anda bisa memverifikasi integritas), dan jalur state yang jelas (mis. pending, uploaded, failed, deleted).

Checklist jarak-akhir:

  • Pastikan retry aman: upaya berulang tidak boleh membuat object ekstra atau baris "uploaded" dengan byte yang hilang.
  • Buat unggahan bisa dilanjutkan atau setidaknya bisa dimulai ulang tanpa tiket dukungan (timeout dan jaringan mobile akan terjadi).
  • Verifikasi unduhan mendukung range request sehingga file besar bisa mulai cepat dan dilanjutkan setelah jeda.
  • Definisikan penghapusan end-to-end: tombstone metadata, hapus byte object, dan tangani pembersihan tertunda jika job gagal.
  • Tambahkan monitoring dasar: tingkat error unggah/unduh, pertumbuhan storage, dan lonjakan egress mendadak.

Satu tes konkret: unggah file 2 GB, refresh halaman pada 30%, lalu lanjutkan. Lalu unduh pada koneksi lambat dan lakukan seek ke tengah. Jika salah satu alur goyah, perbaiki sekarang, bukan setelah peluncuran.

Skenario contoh: foto dan invoice dalam satu aplikasi

Atur unggahan presigned
Buat unggahan langsung ke storage dengan langkah finalize, tanpa memproxy byte file.

Aplikasi SaaS sederhana sering punya dua tipe unggahan yang sangat berbeda: foto profil (sering, kecil, aman di-cache) dan PDF invoice (sensitif, harus privat). Di sinilah pemisahan antara metadata di Postgres dan byte di object storage sangat menguntungkan.

Berikut contoh bagaimana metadata bisa terlihat di satu tabel files, dengan beberapa field yang mempengaruhi perilaku:

kolomcontoh foto profilcontoh invoice PDF
kindavatarinvoice_pdf
visibilityprivate (disajikan via signed URL)private
cache_controlpublic, max-age=31536000, immutableno-store
object_keyusers/42/avatars/2026-01-17T120102Z.webporgs/7/invoices/INV-1049.pdf
statusuploadeduploaded
size_bytes184233982341

Saat pengguna mengganti foto, perlakukan itu sebagai file baru, bukan overwrite. Buat baris baru dan object_key baru, lalu perbarui profil pengguna untuk menunjuk ke file_id baru. Tandai baris lama sebagai replaced_by=<new_id> (atau deleted_at), dan hapus object lama nanti dengan job background. Ini menjaga riwayat, memudahkan rollback, dan menghindari kondisi balapan.

Dukungan dan debugging jadi lebih mudah karena metadata menceritakan kisah. Saat seseorang bilang "unggahan saya gagal," dukungan bisa memeriksa status, last_error yang bisa dibaca manusia, storage_request_id atau etag (untuk menelusuri log storage), timestamps (apakah terjadi stall?), dan owner_id serta kind (apakah kebijakan akses benar?).

Langkah berikutnya untuk mengimplementasikan tanpa membangun berlebihan

Mulai kecil dan buat jalur bahagia yang membosankan: file terunggah, metadata tersimpan, unduhan cepat, dan tidak ada yang hilang.

Tonggak pertama yang baik adalah tabel metadata Postgres minimal plus satu alur unggah dan satu alur unduh yang bisa Anda jelaskan di papan tulis. Setelah itu bekerja end-to-end, tambahkan versi, kuota, dan aturan lifecycle.

Pilih satu kebijakan storage jelas per tipe file dan tuliskan. Misalnya, foto profil bisa di-cache, sedangkan invoice harus privat dan hanya dapat diakses lewat URL unduh berumur pendek. Mencampur kebijakan dalam satu prefix bucket tanpa rencana adalah penyebab kebocoran eksposur tidak sengaja.

Tambahkan instrumentasi sejak awal. Angka yang Anda inginkan sejak hari pertama adalah tingkat kegagalan finalize unggah, tingkat orphan (objek tanpa baris DB yang cocok, dan sebaliknya), volume egress berdasarkan tipe file, P95 latensi unduh, dan ukuran objek rata-rata.

Jika Anda ingin cara cepat untuk mem-prototipe pola ini, Koder.ai (koder.ai) dibangun untuk menghasilkan aplikasi penuh dari chat, dan ia cocok dengan stack umum yang dipakai di sini (React, Go, Postgres). Itu bisa menjadi cara yang membantu untuk iterasi skema, endpoint, dan job pembersihan background tanpa menulis ulang scaffolding berulang-ulang.

Setelah itu, tambahkan hanya apa yang bisa Anda jelaskan dalam satu kalimat: "kami menyimpan versi lama selama 30 hari" atau "setiap workspace mendapat 10 GB." Jaga sederhana sampai penggunaan nyata memaksa Anda berevolusi.

Pertanyaan umum

Haruskah saya menyimpan file yang diunggah di Postgres atau di object storage?

Gunakan Postgres untuk metadata yang perlu Anda query dan amankan (owner, permissions, state, checksum, pointer). Simpan byte di object storage sehingga unduhan dan transfer besar tidak menghabiskan koneksi database atau memperbesar backup.

Apa kekurangan utama menyimpan byte file di blob Postgres?

Ini membuat database Anda berperan ganda sebagai file server. Ukuran tabel bertambah, backup dan restore melambat, replikasi terbebani, dan performa menjadi kurang dapat diprediksi ketika banyak pengguna mengunduh sekaligus.

Arsitektur unggahan sederhana apa yang dapat diskalakan tanpa menjadi rumit?

Iya. Simpan satu file_id stabil di aplikasi Anda, simpan metadata di Postgres, dan simpan byte di object storage yang diakses lewat bucket dan object_key. API Anda sebaiknya mengotorisasi akses dan mengeluarkan izin unggah/unduh berumur pendek alih-alih memproxy byte.

Bagaimana alur unggahan sebaiknya jika saya tidak ingin API saya menangani byte file?

Buat row pending dulu, hasilkan object_key unik, lalu biarkan klien mengunggah langsung ke storage menggunakan izin berumur pendek. Setelah unggah, minta klien memanggil endpoint finalize agar server dapat memverifikasi ukuran dan checksum (jika dipakai) sebelum menandai row sebagai uploaded.

Kenapa saya perlu state unggahan seperti pending/uploaded/failed/deleted?

Karena unggahan nyata gagal dan retry. Field state memungkinkan Anda membedakan file yang diharapkan tapi belum ada (pending), selesai (uploaded), rusak (failed), dan dihapus (deleted) sehingga UI, job pembersihan, dan alat dukungan berperilaku benar.

Bolehkan saya menggunakan nama file yang diberikan user sebagai object key di storage?

Anggap original_filename hanya untuk ditampilkan. Hasilkan key storage unik (seringkali path berbasis UUID) untuk menghindari tabrakan, karakter aneh, dan masalah keamanan. Anda tetap bisa menampilkan nama asli di UI sambil menjaga path storage bersih dan dapat diprediksi.

Polanya seperti apa untuk mengunduh file privat?

Gunakan URL aplikasi stabil seperti /files/{file_id} sebagai gerbang izin. Setelah memeriksa akses di Postgres, kembalikan redirect atau izin unduh signed berumur pendek sehingga klien mengunduh langsung dari object storage, menjaga API Anda tetap di luar hot path.

Apa yang biasanya menyebabkan biaya mengejutkan dengan unggahan user?

Egress dan unduhan berulang biasanya dominan, bukan hanya penyimpanan mentah. Batasi ukuran file dan tetapkan kuota, gunakan aturan retensi/lifecycle, deduplikasi berdasarkan checksum bila masuk akal, dan simpan counter penggunaan sehingga Anda bisa memberi peringatan sebelum tagihan melonjak.

Pemeriksaan keamanan apa yang layak dilakukan untuk unggahan di hari pertama?

Simpan permissions dan visibility di Postgres sebagai sumber kebenaran, dan jadikan storage privat secara default. Validasi tipe dan ukuran sebelum dan setelah unggah, gunakan HTTPS end-to-end, enkripsi di rest, dan tambahkan field audit sehingga Anda bisa menyelidiki masalah nanti.

Bagaimana saya bisa mengimplementasikan ini cepat tanpa membangun berlebihan?

Mulai dengan satu tabel metadata, satu alur unggah langsung-ke-storage, dan satu endpoint gate unduh, lalu tambahkan job pembersihan untuk objek orphan dan row soft-deleted. Jika ingin prototipe cepat di stack React/Go/Postgres, Koder.ai dapat menghasilkan endpoint, skema, dan task background dari chat sehingga Anda bisa iterasi tanpa menulis ulang boilerplate.

Related posts