If you have ever tried to integrate IPFS (InterPlanetary File System) into a traditional web application, you’ve likely stumbled upon the worst-kept secret of decentralization: public gateway latency.
The core concept is brilliant: you upload a PDF, get a unique and immutable CID (Content Identifier), and you’re good to go. The file is secure, distributed, and tamper-proof. But the moment you need to pass that file, for exampleto a browser-based PDF viewer, a major hurdle arises: Which public gateway will respond first? And what if that specific gateway is down today?

Today, we’ll explore how I solved this issue on the backend, optimizing performance using a parallel gateway racing system and smart caching.
The Problem: The IPFS Gateway Lottery
To display an IPFS file inside an iframe or a JavaScript viewer, we need a public HTTP gateway (such as Cloudflare, Pinata, or Web3.Storage) to translate the IPFS protocol into a standard https:// URL.
The catch is that public gateways are highly unpredictable:
- A gateway might be lightning-fast right now and painfully slow five minutes later.
- Some will time out if the file hasn’t fully propagated across the network yet.
- Hardcoding a single gateway introduces a single point of failure (SPOF).
The solution? Pit the gateways against each other.
First one to respond wins.
Architecture of the Solution (In a Nutshell…)
To guarantee maximum loading speeds for the Document Viewer, we have implemented a three-step strategy:
– Session Memory: It remembers the last gateway that responded successfully during the user’s active session.
– Parallel Gateway Racing: If the preferred gateway fails or lags, it queries a list of alternative gateways simultaneously using asynchronous HTTP requests.
– Smart Caching & Fallback: It caches the winning URL (e.g., via SQLite or JSON) to avoid re-running the race on every page refresh. If the entire IPFS network is unreachable, it seamlessly falls back to a locally stored file.
Implementation: The curl_multi_init Trick
Here is a conceptual Snippet showing how to implement parallel checks in PHP. Instead of testing gateways sequentially (which would take ages), we fire off HEAD requests all at once.
PHP
// A list of public gateways to put to the test
$default_gateways = [
'https://gateway.pinata.cloud/ipfs',
'https://cloudflare-ipfs.com/ipfs',
'https://w3s.link/ipfs'
];
function checkIPFSGatewayParallel($cid, $gateways) {
$mh = curl_multi_init();
$chs = [];
// Prepare asynchronous requests (HEAD only, to keep it lightning fast)
foreach ($gateways as $gateway) {
$url = rtrim($gateway, '/') . '/' . $cid;
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_NOBODY, true); // Don't download the PDF, just look for a 200 OK
curl_setopt($ch, CURLOPT_TIMEOUT, 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_multi_add_handle($mh, $ch);
$chs[$gateway] = $ch;
}
// Execute handles in parallel
$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
$found_url = false;
// ... descriptor read loop ...
// The first gateway to return HTTP Code 200 breaks the loop and wins the race!
return $found_url;
}
Why is this approach so efficient?
By setting CURLOPT_NOBODY = true, we issue a HEAD request. We aren’t downloading the actual PDF (which could be several megabytes); we are merely asking the gateway: “Hey, do you have this CID ready to serve?“. The first one to reply with a 200 OK wins the right to serve the file to our viewer.
Here the Global Logical Flow; within the application lifecycle, verifying the CID follows an optimized pipeline:
1 – Cache Check: Has this CID been linked to a working gateway in the last hour? If yes, use it.
2 – Fast Track: Try the gateway stored in the user’s session ($_SESSION[‘preferred_gateway’]). Estimated latency: just a few milliseconds.
3 – The Race: If the Fast Track fails, the parallel race described above triggers. The winner is saved to both the session and the cache.
4 – Hard Fallback: If the IPFS network is experiencing temporary congestion, the system switches to the local file system (uploads/file.pdf), ensuring the user always sees their document.
Once the definitive URL is fetched (whether from IPFS or local storage), you simply pass it to your client-side viewer (like an iframe or to a webpage instance), and you are good to go.
Want to Skip the Headache?
Dealing with cURL timeouts, configuring caching databases, managing local fallbacks, and tweaking viewers to avoid CORS issues with IPFS gateways can quickly turn into a micro-management nightmare.
If you want to integrate an immutable, decentralized, and blazing-fast Document Management System into your projects without writing, testing, and maintaining all this backend boilerplate… well, there’s Dokky Suite. It handles exactly this (and a whole lot more) natively, with just one click. 😉



