Als je file_exists($path) aanroept en $path verwijst naar een Amazon S3-bucket, dan raak je geen lokale schijf aan — je doet een netwerkverzoek. De controle in één regel wordt een round-trip naar S3 die tientallen milliseconden aan elke aanvraag kan toevoegen.

PHP verbergt de externe opslag achter stream wrappers. Functies zoals fopen(), file_exists(), is_dir(), unlink() en file_put_contents() worden via deze wrappers afgehandeld, die de aanroepen vertalen naar S3 API-bewerkingen. De koppeling is rechttoe rechtaan:

  • file_exists()HeadObject
  • is_dir()ListObjects
  • unlink()DeleteObject
  • file_put_contents()PutObject

Elke aanroep brengt dezelfde latentie met zich mee als het bijbehorende S3 API-verzoek. Wanneer een script tientallen bestanden controleert, ontstaat er een N+1-patroon: één netwerkstap voor elke afzonderlijke controle.

Waarom dit nu belangrijk is

In een typische ontwikkelomgeving bevindt het bestandssysteem zich op dezelfde machine, waardoor de controle bijna onmiddellijk resultaat geeft. In productie, waar assets op S3 staan, zorgt dezelfde code voor een enorme prestatiedaling. De AWS SDK cachet sommige resultaten in het geheugen, waardoor herhaalde controles binnen één enkel PHP-proces snel lijken. De meeste PHP-deployments starten echter voor elk webverzoek een nieuw proces op, waardoor de cache telkens wordt geleegd. Het resultaat: een volledige netwerk-round-trip voor elk afzonderlijk pad bij elk verzoek.

Een WordPress-site deed er ooit tien seconden over om de homepage te renderen. Database-queries waren snel, maar de pagina triggerde 73 individuele S3-aanroepen om alleen al de inhoud samen te stellen. Elke aanroep was een 'cold request', waardoor een schijnbaar onschuldige file_exists() veranderde in een merkbare vertraging.

Mitigatiestrategieën

  • Cache behouden over verzoeken heen – Verplaats de in-process cache naar een gedeelde opslag zoals Redis. Wanneer een verzoek ontdekt dat een sleutel op S3 bestaat, lezen opeenvolgende verzoeken het gecachte resultaat in plaats van opnieuw contact op te nemen met S3.
  • Hanteer een local-first workflow – Schrijf bestanden naar een lokale schijf en synchroniseer ze vervolgens asynchroon met S3. Het hoofdpad van het verzoek raakt alleen het lokale bestandssysteem; de netwerkkosten verschuiven naar een achtergrondtaak.
  • Audit de codebase – Zoek systematisch naar bestandssysteemfuncties die naar een externe wrapper kunnen verwijzen. Markeer functies die voorkomen in strakke loops of paden die kritiek zijn voor het verzoek.
  • Inspecteer APM-gegevens – Als de responstijd piekt terwijl de database-metrieken stabiel blijven, duik dan in de timing van de storage SDK. Een plotselinge stijging in SDK-latentie wijst vaak op verborgen S3-aanroepen.

De belangrijkste les: een functie die lijkt op een lokale controle van een microseconde, kan tientallen milliseconden aan netwerklatentie verbergen. Behandel file_exists() op S3 als een externe aanroep, cache het resultaat en verplaats het zware werk buiten het verzoekspad. Anders zal verborgen latentie je site blijven vertragen, één onzichtbaar netwerkverzoek per keer.