zpl.tools
Performance

zpl.tools and Labelary

Response time, accepted page counts and response size, measured 2026-08-17

Labelary is a hosted service: api.labelary.com, the hosted rendering API. This page compares it with zpl.tools — api.zpl.tools, the Labelary-compatible surface. One client sends both requests over the same connection, so both sides carry the same network time.

Labelary documents two limits on a request: 50 labels, and a 1 MB request body.

Response time

Median response time, orderful style
  • zpl.tools
  • Labelary
02505007501,0000100200300400500Pages per requestMedian response, ms846 ms400 ms
Orderful style, PDF.
Values behind this chart
Engine1 p2 p3 p4 p5 p10 p15 p20 p25 p30 p35 p40 p45 p50 p75 p100 p150 p200 p300 p500 p
zpl.tools53 ms55 ms58 ms54 ms51 ms56 ms73 ms76 ms84 ms85 ms99 ms99 ms107 ms129 ms165 ms207 ms281 ms349 ms492 ms846 ms
Labelary110 ms111 ms113 ms124 ms117 ms139 ms252 ms270 ms283 ms292 ms364 ms319 ms374 ms400 ms0%0%

On one page, zpl.tools answers in a median 53 ms and Labelary in 110 ms, a factor of 2.1. At 50 pages, the largest packet the benchmark sent to both engines, the medians are 129 ms and 400 ms. zpl.tools rendered 500 pages in a median 846 ms, and 500 pages is where the benchmark stopped — the renderer sets no page limit. Labelary rejects a request past 50 pages.

Accepted requests

Labelary rejected the request of 75 pages on the orderful style corpus, and every larger request. The chart draws the share of requests that returned 200. It drops from 100% to 0% at that page count.

Accepted requests, orderful style
  • zpl.tools
  • Labelary
0%25%50%75%100%0100200300400500Pages per requestRenders that returned 200rejected from 75 pages100%0%
Orderful style, PDF.
Values behind this chart
Engine1 p2 p3 p4 p5 p10 p15 p20 p25 p30 p35 p40 p45 p50 p75 p100 p150 p200 p300 p500 p
zpl.tools100%100%100%100%100%100%100%100%100%100%100%100%100%100%100%100%100%100%100%100%
Labelary100%100%100%100%100%100%100%100%100%100%100%100%100%100%0%0%

zpl.tools accepted every page count the run measured, up to 500 pages.

Response size

PDF response size, orderful style
  • zpl.tools
  • Labelary
0 B244.1 KB488.3 KB732.4 KB0100200300400500Pages per requestResponse body791.0 KB143.1 KB
Orderful style, PDF.
Values behind this chart
Engine1 p2 p3 p4 p5 p10 p15 p20 p25 p30 p35 p40 p45 p50 p75 p100 p150 p200 p300 p500 p
zpl.tools13.9 KB15.9 KB18.1 KB20.9 KB23.6 KB42.2 KB52.3 KB63.4 KB72.7 KB82.3 KB92.4 KB101.3 KB110.2 KB119.5 KB162.8 KB203.5 KB290.9 KB361.5 KB504.9 KB791.0 KB
Labelary17.4 KB19.7 KB22.0 KB25.8 KB28.3 KB53.5 KB67.1 KB79.4 KB90.6 KB101.3 KB112.4 KB121.8 KB132.4 KB143.1 KB0%0%

A one-page PDF from zpl.tools is 13.9 KB. At 500 pages the same response is 791.0 KB: 56.8 times the size for 500 times the pages. The PDF writer stores one copy of a repeated page and references it, so a packet grows by its per-page content, not by a whole page. At 50 pages, the response is 119.5 KB against 143.1 KB from Labelary.

Corpora

Each corpus is one request body, repeated at every page count. A corpus reaches this page only where the run measured both engines on it.

Simple label

Labelary's own example label, duplicated per page. Every page carries the same label.

Pageszpl.tools p50zpl.tools p90zpl.tools p95Labelary p50Labelary p90Labelary p95
155 ms171 ms523 ms109 ms216 ms241 ms
1048 ms86 ms104 ms125 ms163 ms247 ms
5092 ms98 ms120 ms300 ms466 ms524 ms
100156 ms165 ms179 msrejectedrejectedrejected
500521 ms596 ms606 ms

GS1 graphics label

A real retailer label with embedded ~DG graphics, duplicated per page. Every page carries the same label.

Pageszpl.tools p50zpl.tools p90zpl.tools p95Labelary p50Labelary p90Labelary p95
145 ms53 ms58 ms247 ms395 ms406 ms
1073 ms82 ms89 ms337 ms378 ms496 ms
50162 ms189 ms263 msrejectedrejectedrejected
100228 ms293 ms356 msrejectedrejectedrejected
500891 ms1,003 ms1,036 ms

Orderful style

Orderful retail compliance labels, a different label on every page. Every page carries a different label, so no engine can reuse a page it already rendered.

Pageszpl.tools p50zpl.tools p90zpl.tools p95Labelary p50Labelary p90Labelary p95
153 ms56 ms56 ms110 ms149 ms179 ms
1056 ms65 ms65 ms139 ms229 ms363 ms
50129 ms136 ms137 ms400 ms495 ms635 ms
100207 ms209 ms211 msrejectedrejectedrejected
500846 ms962 ms965 ms

SPS Style

The same retailer labels delivered as ~DG bitmap pages, the SPS Commerce way. Every page carries a different label, so no engine can reuse a page it already rendered.

Pageszpl.tools p50zpl.tools p90zpl.tools p95Labelary p50Labelary p90Labelary p95
171 ms79 ms82 ms338 ms374 ms467 ms
10155 ms189 ms202 msrejectedrejectedrejected
50536 ms775 ms797 msrejectedrejectedrejected
100997 ms1,399 ms1,403 msrejectedrejectedrejected

Method

k6 drives every point, one request at a time, 10 iterations per point, 5 past 150 pages. A one-page point carries 10 samples.

Client: k6, one request at a time. Both hosted engines measured in the same session from a Hetzner ccx13 (dedicated vCPU) in the fsn1 datacenter, Germany — network RTT included, the same for both sides. Local engines measured on a MacBook Pro (Apple Silicon), no network crossed; the zpl.tools, zebrash, BinaryKits and Neodynamic summaries carry over from the 2026-08-09 run, because no code in the render path changed between them. labelize was added on 2026-08-17 and measured on the same MacBook, at one page only — see below.

Measured 2026-08-17. The harness is benchmarks/run.sh, and its header names the local servers each engine needs. To repeat the run:

./benchmarks/run.sh
node scripts/distill-benchmarks.mjs
node scripts/generate-performance-pages.mjs

The first command measures, the second writes website/lib/performance-data.json, and the third writes this page from it.