Jika Anda memanggil file_exists($path) dan $path mengarah ke bucket Amazon S3, Anda tidak sedang mengakses disk lokal—Anda sedang melakukan permintaan jaringan. Pemeriksaan satu baris tersebut menjadi perjalanan bolak-balik (round-trip) ke S3 yang dapat menambah puluhan milidetik pada setiap permintaan.
PHP menyembunyikan penyimpanan jarak jauh di balik stream wrappers. Fungsi-fungsi seperti fopen(), file_exists(), is_dir(), unlink(), dan file_put_contents() diarahkan melalui wrapper ini, yang menerjemahkan panggilan tersebut menjadi operasi API S3. Pemetaannya sangat sederhana:
file_exists()→ HeadObjectis_dir()→ ListObjectsunlink()→ DeleteObjectfile_put_contents()→ PutObject
Setiap panggilan mengalami latensi yang sama dengan permintaan API S3 yang bersangkutan. Ketika sebuah skrip memeriksa puluhan file, hal ini menciptakan pola gaya N+1: satu lompatan jaringan (network hop) untuk setiap pemeriksaan.
Mengapa ini penting sekarang
Dalam lingkungan pengembangan tipikal, sistem berkas berada di mesin yang sama, sehingga pemeriksaan hampir seketika. Di produksi, di mana aset berada di S3, kode yang sama menciptakan penurunan performa yang drastis (performance cliff). AWS SDK menyimpan beberapa hasil di memori, membuat pemeriksaan berulang dalam satu proses PHP tampak cepat. Namun, sebagian besar penerapan PHP meluncurkan proses baru untuk setiap permintaan web, sehingga menghapus cache setiap saat. Hasilnya: perjalanan bolak-balik jaringan penuh untuk setiap jalur unik pada setiap permintaan.
Sebuah situs WordPress pernah membutuhkan sepuluh detik untuk merender halaman berandanya. Kueri database berjalan cepat, tetapi halaman tersebut memicu 73 panggilan S3 individual hanya untuk menyusun konten. Setiap panggilan adalah permintaan dingin (cold request), mengubah file_exists() yang tampak tidak berbahaya menjadi penundaan yang nyata.
Strategi mitigasi
- Persist cache antar permintaan – Pindahkan cache dalam proses ke penyimpanan bersama seperti Redis. Ketika satu permintaan menemukan bahwa sebuah kunci ada di S3, permintaan berikutnya akan membaca hasil yang tersimpan di cache alih-alih menghubungi S3 lagi.
- Adopsi alur kerja local-first – Tulis file ke disk lokal, lalu sinkronkan ke S3 secara asinkron. Jalur permintaan utama hanya menyentuh sistem berkas lokal; biaya jaringan dialihkan ke pekerjaan latar belakang (background job).
- Audit basis kode – Cari secara sistematis fungsi sistem berkas yang mungkin merujuk ke remote wrapper. Tandai fungsi apa pun yang muncul di dalam loop yang ketat atau jalur kritis permintaan.
- Periksa data APM – Jika waktu respons melonjak sementara metrik database tetap stabil, teliti waktu SDK penyimpanan. Kenaikan mendadak pada latensi SDK sering kali menunjukkan adanya panggilan S3 yang tersembunyi.
Kesimpulan utamanya: sebuah fungsi yang tampak seperti pemeriksaan lokal berdurasi mikrodetik dapat menyembunyikan latensi jaringan puluhan milidetik. Perlakukan file_exists() pada S3 sebagai panggilan eksternal, simpan hasilnya di cache, dan pindahkan beban kerja berat keluar dari jalur permintaan. Jika tidak, latensi tersembunyi akan terus memperlambat situs Anda, satu per satu permintaan jaringan yang tidak terlihat.
