Caching patterns
These caching patterns apply to every Microlink workflow: screenshots, PDFs, data extraction, metadata, and insights. Each guide's own caching page covers the workflow-specific speedups; this page covers the shared cache controls.
How caching works
Every Microlink response is cached for 24 hours by default. The cache is two-layered:
- Unified cache — the first request creates a shared copy (
x-cache-status: MISS). Subsequent requests serve that copy (HIT). - Edge node cache — after the unified cache is warm, responses are also served from the nearest CloudFlare edge node.
See the cache docs for the full architecture.
Cache TTL PRO
Use
ttl to control how long a response stays valid before expiring:The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://microlink.io' URL with 'ttl' API parameter:
CLI Microlink API example
microlink https://microlink.io&ttl=1dcURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://microlink.io" \
-d "ttl=1d"JavaScript Microlink API example
import mql from '@microlink/mql'
const { data } = await mql('https://microlink.io', {
ttl: "1d"
})Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://microlink.io",
"ttl": "1d"
}
response = requests.get(url, params=querystring)
print(response.json())Ruby Microlink API example
require 'uri'
require 'net/http'
base_url = "https://api.microlink.io/"
params = {
url: "https://microlink.io",
ttl: "1d"
}
uri = URI(base_url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://microlink.io",
"ttl" => "1d"
];
$query = http_build_query($params);
$url = $baseUrl . '?' . $query;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET"
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #: " . $err;
} else {
echo $response;
}Golang Microlink API example
package main
import (
"fmt"
"net/http"
"net/url"
"io"
)
func main() {
baseURL := "https://api.microlink.io"
u, err := url.Parse(baseURL)
if err != nil {
panic(err)
}
q := u.Query()
q.Set("url", "https://microlink.io")
q.Set("ttl", "1d")
u.RawQuery = q.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}import mql from '@microlink/mql'
const { data } = await mql('https://microlink.io', {
ttl: "1d"
})After the TTL expires, the next request generates a fresh response.
The value must be between 1 minute and 31 days. It accepts milliseconds or humanized strings:
ttl=90s # 90 seconds
ttl=1h # 1 hour
ttl=1d # 1 day (24 hours)
ttl=7d # 7 days
ttl=min # alias for 1 minute
ttl=max # alias for 31 daysChoose your TTL based on how often the target content changes:
| Content type | Recommended TTL |
|---|---|
| Rapidly changing (dashboards, feeds) | '1h' or less |
| Moderate changes (blogs, docs, marketing pages) | '1d' to '7d' |
| Rarely changing (static docs, stable references) | 'max' (31 days) |
The TTL is reflected in the
x-cache-ttl response header. See the ttl reference for all supported formats.Stale-while-revalidate PRO
The
staleTtl parameter serves the cached response immediately while refreshing it in the background:The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://microlink.io' URL with 'ttl' & 'staleTtl' API parameters:
CLI Microlink API example
microlink https://microlink.io&ttl=1d&staleTtl=0cURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://microlink.io" \
-d "ttl=1d" \
-d "staleTtl=0"JavaScript Microlink API example
import mql from '@microlink/mql'
const { data } = await mql('https://microlink.io', {
ttl: "1d",
staleTtl: 0
})Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://microlink.io",
"ttl": "1d",
"staleTtl": "0"
}
response = requests.get(url, params=querystring)
print(response.json())Ruby Microlink API example
require 'uri'
require 'net/http'
base_url = "https://api.microlink.io/"
params = {
url: "https://microlink.io",
ttl: "1d",
staleTtl: "0"
}
uri = URI(base_url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://microlink.io",
"ttl" => "1d",
"staleTtl" => "0"
];
$query = http_build_query($params);
$url = $baseUrl . '?' . $query;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET"
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #: " . $err;
} else {
echo $response;
}Golang Microlink API example
package main
import (
"fmt"
"net/http"
"net/url"
"io"
)
func main() {
baseURL := "https://api.microlink.io"
u, err := url.Parse(baseURL)
if err != nil {
panic(err)
}
q := u.Query()
q.Set("url", "https://microlink.io")
q.Set("ttl", "1d")
q.Set("staleTtl", "0")
u.RawQuery = q.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}import mql from '@microlink/mql'
const { data } = await mql('https://microlink.io', {
ttl: "1d",
staleTtl: 0
})With
staleTtl: 0, every request serves the cached copy instantly and triggers a background refresh.This is the recommended production pattern. Your users always get an instant response, and the content stays reasonably fresh. The
staleTtl value cannot exceed the ttl value.| Pattern | Behavior |
|---|---|
staleTtl: 0 | Always serve cache, always revalidate in background |
staleTtl: '12h' | Serve cache for 12 hours, then revalidate |
staleTtl: false | Disabled (default) — no stale serving |
See the staleTtl reference for all supported formats.
Bypassing the cache
Use
force: true to skip the cache entirely and get a fresh response:The following examples show how to use the Microlink API with CLI, cURL, JavaScript, Python, Ruby, PHP & Golang, targeting 'https://microlink.io' URL with 'force' API parameter:
CLI Microlink API example
microlink https://microlink.io&forcecURL Microlink API example
curl -G "https://api.microlink.io" \
-d "url=https://microlink.io" \
-d "force=true"JavaScript Microlink API example
import mql from '@microlink/mql'
const { data } = await mql('https://microlink.io', {
force: true
})Python Microlink API example
import requests
url = "https://api.microlink.io/"
querystring = {
"url": "https://microlink.io",
"force": "true"
}
response = requests.get(url, params=querystring)
print(response.json())Ruby Microlink API example
require 'uri'
require 'net/http'
base_url = "https://api.microlink.io/"
params = {
url: "https://microlink.io",
force: "true"
}
uri = URI(base_url)
uri.query = URI.encode_www_form(params)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Get.new(uri)
response = http.request(request)
puts response.bodyPHP Microlink API example
<?php
$baseUrl = "https://api.microlink.io/";
$params = [
"url" => "https://microlink.io",
"force" => "true"
];
$query = http_build_query($params);
$url = $baseUrl . '?' . $query;
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET"
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #: " . $err;
} else {
echo $response;
}Golang Microlink API example
package main
import (
"fmt"
"net/http"
"net/url"
"io"
)
func main() {
baseURL := "https://api.microlink.io"
u, err := url.Parse(baseURL)
if err != nil {
panic(err)
}
q := u.Query()
q.Set("url", "https://microlink.io")
q.Set("force", "true")
u.RawQuery = q.Encode()
req, err := http.NewRequest("GET", u.String(), nil)
if err != nil {
panic(err)
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
}import mql from '@microlink/mql'
const { data } = await mql('https://microlink.io', {
force: true
})The response header
x-cache-status will be BYPASS. Use sparingly — this always triggers a fresh request.Verify caching behavior
Check these response headers to confirm the request behaved as expected:
| Header | What it tells you |
|---|---|
x-cache-status | HIT (served from cache), MISS (fresh), or BYPASS (forced) |
x-cache-ttl | The effective cache lifetime in milliseconds |
cf-cache-status | CloudFlare edge cache status |
x-response-time | Total request duration — fast times usually indicate a cache hit |