# QR codes in serverless functions

> Pure-JavaScript QR generators run in every serverless runtime with negligible cold-start cost — encoding is milliseconds and the library is small. The pitfall is native dependencies for PNG rasterisation, which break on mismatched platform binaries. Emit SVG from the function, or skip the function entirely and embed a keyless API URL.

Source: https://useqr.app/docs/developers/qr-codes-in-serverless-functions · Last reviewed 2026-08-21 · UseQR is free forever, MIT licensed, no signup.

---

## Serverless suits QR generation unusually well

A QR render is stateless, CPU-light and pure — the exact workload functions were made
for. Encoding takes [microseconds to milliseconds](/docs/developers/qr-code-generation-performance),
needs no database and no warm state, so cold starts add nothing beyond module load.
UseQR's own API runs this way: every generate, decode and verify endpoint is a
serverless function on Vercel's Node runtime.

The problems people actually hit are packaging problems, not compute problems.

## The native-dependency trap

Pure-JS generation works everywhere:

```js
// Lambda / Vercel / Netlify — Node runtime
import QRCode from "qrcode";

export async function handler(event) {
  const data = event.queryStringParameters?.data ?? "hello";
  const svg = await QRCode.toString(data, { type: "svg", errorCorrectionLevel: "M" });
  return { statusCode: 200, headers: { "Content-Type": "image/svg+xml" }, body: svg };
}
```

The `qrcode` package is pure JavaScript with no native binaries, so this deploys to any
Node-compatible runtime unchanged and keeps the bundle far below the sizes where
cold starts hurt.

Trouble starts with **PNG**. Rasterising SVG to pixels needs a real renderer —
`sharp`, `canvas`, `@resvg/resvg-js` — and all of them ship platform-specific native
binaries. The classic failure: `npm install` on a macOS laptop bundles Darwin
binaries, and the Linux function dies at import time. The fixes are known
(platform-targeted installs, layers, container images), but each one is
maintenance you now own. UseQR runs `@resvg/resvg-js` in its functions, and pinning
that correctly per platform is genuine, ongoing work.

Three ways to avoid owning it:

1. **Return SVG.** Browsers render it, email mostly does not — know your consumer.
2. **Return the matrix as JSON** and draw client-side ([the pattern](/docs/spec/rendering-a-qr-code-from-a-matrix)).
3. **Delegate PNG to a keyless API** — see below.

**Edge runtimes** (Cloudflare Workers, Vercel Edge) sharpen the same constraint: no
native binaries at all, and WASM must fit tight size budgets. Pure-JS encode-to-SVG is
comfortably within them.

## Set the right headers, then stop worrying about load

QR output is deterministic, so a serverless QR endpoint should send
`Cache-Control: public, max-age=31536000, immutable` and let the CDN absorb repeat
traffic — after which your function renders each unique parameter set roughly once.
Skipping this is the most common self-inflicted serverless bill. Details:
[caching and CDN strategy](/docs/developers/caching-and-cdn-strategy-for-qr-images).
Streaming, for completeness, buys little here — a QR PNG is tens of kilobytes, well
under the thresholds where streaming responses matter.

## When the function should not exist

Be honest about why the function is there. If it only turns a payload into an image —
no private data, no custom branding pipeline — you can delete it and embed a URL:

```
https://useqr.app/api/v1/qr?data=hello&size=512
```

Keyless, [no signup](/docs/developers/free-qr-code-api-no-key), deterministic,
immutable-cached, CORS-open, with typed endpoints for
[WiFi](/wifi-qr-code), [UPI](/upi-qr-code) and friends. Zero cold starts, zero
maintenance, zero platform binaries — the strongest serverless architecture is often
no server at all. Keep your own function when the payload is sensitive (generate
[client-side](/docs/security/client-side-vs-server-side-qr-generation) or in-process
instead of calling any third party), or when generation is fused with logic that must
stay yours.

## FAQ

### Can I generate QR codes in AWS Lambda?
Yes, trivially, if you emit SVG with a pure-JavaScript library — no native dependencies, small bundle, milliseconds of compute. PNG output needs a native rasteriser built for Amazon Linux, which is where deployments usually break.

### Why does my QR function fail with a binary or module error?
A native rasterisation dependency (sharp, canvas, resvg) was installed for your laptop's platform, not the function's Linux runtime. Install with the target platform flag, use a layer or container image, or switch to SVG output.

### Do QR codes work in Cloudflare Workers?
Yes — encoding is pure computation and fits the edge runtime easily. Emit SVG or a JSON matrix; native PNG rasterisers cannot run there, though a WASM rasteriser can if it fits your size budget.

### Should I build a QR function or use an API?
If the function only converts public payloads to images, a keyless API URL does the same job with no cold starts and no maintenance. Build your own when payloads are sensitive or generation is entangled with your business logic.

## Try it

- https://useqr.app/url
- https://useqr.app/json
- https://useqr.app/base64
