Function: Profiling and performance
Every function response includes profiling data with phase-level timing and resource usage.
Profiling
import createClient from 'microlink.io'
const microlink = createClient()
const { profiling } = await microlink.function('https://example.com', ({ page }) => page.title())
console.log(profiling)
// {
// phases: { install: 0, build: 120, spawn: 45, run: 890, total: 1055 },
// cpu: 234,
// memory: { total: 69996544, used: 2359296, heap: 4410880, external: 1742574 },
// size: 156
// }| Field | Description |
|---|---|
phases.install | Time spent installing npm dependencies (0 when none are used) |
phases.build | Time spent bundling the function code |
phases.spawn | Time spent starting the isolated process |
phases.run | Time spent executing the function |
phases.total | Wall-clock time from start to finish |
cpu | Peak CPU time in milliseconds |
memory.total | Resident memory of the sandbox, Node.js baseline included, in bytes |
memory.used | Resident memory attributable to your function, in bytes |
memory.heap | V8 heap in use, in bytes. The only field the memory limit bounds |
memory.external | Off-heap Buffer/ArrayBuffer memory, in bytes |
size | Bundled code size in bytes |
Use profiling to understand where time is spent. If install is high, your dependencies are being installed for the first time — subsequent runs use the cache. If run is high, the function itself is doing heavy work.
Plan limits
The function parameter is available on both free and pro plans:
| Free plan | Paid plan | |
|---|---|---|
| Timeout | 15 seconds | 60 seconds |
| Memory | 64 MB | 128 MB |
| Code size | 1024 bytes | Unlimited |
| Concurrency | 2 concurrent requests | Unlimited |
| Outgoing requests | Same-origin only | Unrestricted |
A free API key is enough to prototype workflows and run the examples in this guide;
headers, proxy, ttl and staleTtl are included. For production workloads that need more volume, use a paid plan.To authenticate, pass your API key:
import createClient from 'microlink.io'
const microlink = createClient({
apiKey: process.env.MICROLINK_API_KEY
})
const { value } = await microlink.function('https://example.com', ({ page }) => page.title())See the authentication and rate limit docs for endpoint and quota details.
When the page is fetched
A function-only request pays for the function and nothing else: normalized metadata is off by
default, and the page is resolved only when your code needs it.
| your function | what the request does |
|---|---|
never mentions page | nothing is fetched |
calls page.content(), page.extract() or page.metadata() | the page is fetched at the moment you call it |
drives the browser, such as page.click() or page.evaluate() | the page is loaded once and your function runs on it |
The fetch happens on the call, not before your function starts.
Destructure
page itself rather than its methods. ({ page }) => page.content() is answered from
fetched HTML with no browser, while ({ page: { content } }) => content() cannot be read ahead of
time and starts a full browser.Ask for meta explicitly when you want normalized metadata alongside the
function, or call page.metadata inside it to get the same data for one page load:
import createClient from 'microlink.io'
const microlink = createClient()
const { value } = await microlink.function(
'https://example.com',
async ({ page }) => (await page.metadata()).title
)
console.log(value)page.metadata() returns the same fields as meta.Compression
Function bodies travel in the URL, so large ones are compressed before they are sent. The SDK does it for you:
microlink.function() compresses the code with brotli when the runtime supports it, falls back to gzip otherwise, and prefixes the payload with br# or gz#. The call stays the same.If you call the API directly, compress the function body and prefix the payload with the alias of the algorithm:
br#for brotligz#for gziplz#for lz-string
The free plan's 1024 bytes code size limit applies to the code once decompressed, so compression keeps the URL short but does not raise the limit. Read how to compress to know more.
Optimization checklist
- Leave metadata off — a function-only request already skips it. Ask for
meta: trueonly when you genuinely want it, since it is usually the largest cost in the request. - Use
page.title()andpage.$eval()instead ofpage.evaluate()when possible — they are faster and easier to debug. - Replace fixed waits like
page.waitForTimeout(3000)withpage.waitForSelector()— they resolve as soon as the element appears. - Check
profiling.phasesto find the bottleneck — a high install on first run is normal, but a high run means the function itself needs work. - Minimize dependencies — each
require()adds install and build time. Use only what you need.
See also
- Troubleshooting — error handling, resource errors, and debugging.
- Common caching patterns — reduce cost and improve response speed.
- Function reference — response shape, plan limits, and compression.