posthog-js@1.435.8 · seven submodules · LilScript port

PostHog,
compiled.

Seven submodules of posthog-js@1.435.8 rewritten in LilScript: exception capture, browser and device detection, autocapture utilities, feature-flag responses, the metrics client, UUIDv7 ids and request gzip. Each one is compared on its own with PostHog’s own build of the same code, and with esbuild and Oxc.

LilScript versus the smallest of PostHog’s build, esbuild and Oxc · seven submodules 21/21cells smaller

17,234 B PostHog’s build → 16,953 B LilScript · Brotli-11, all seven

7.1% smallerraw vs PostHog’s build, all seven
1.6% smallergzip-9 vs PostHog’s build, all seven
1.6% smallerBrotli-11 vs PostHog’s build, all seven
1,076/1,076upstream tests passing on PostHog’s build pass on ours

Raw, gzip and Brotli each use a separate LilScript compilation targeting that objective. Each submodule is compared on its own; the totals add the seven.

Exception capture ✦ Browser, OS and device detection ✦ Autocapture DOM utilities ✦ Feature flag responses ✦ Metrics client ✦ UUIDv7 ids ✦ Request compression ✦ Exception capture ✦ Browser, OS and device detection ✦ Autocapture DOM utilities ✦ Feature flag responses ✦ Metrics client ✦ UUIDv7 ids ✦ Request compression

Pick a module

Size and speed,
module by module.

Each tab is one submodule; the first adds up all seven. Under it: the size of every build for raw, gzip and Brotli against PostHog’s own build, esbuild and Oxc, the speed in Chromium against PostHog’s build, the build time and the upstream tests — every measured file linked.

All seven submodules

Totals of the seven submodules, each measured on its own. For each codec, a module’s original is its smallest upstream build (PostHog’s build, esbuild or Oxc); the LilScript side is the build compiled for that codec.

Upstreampackages/{core,browser-common}/src/… Portsrc/posthog/… BehaviourAll 1,076 of 1,076 upstream tests that pass against PostHog’s build pass against LilScript’s (21 files). 38 more fail against both: their mocks reach private names PostHog’s build mangles. Cells21 of 21 smaller

All seven submodules · size

Three objectives, measured separately.

Raw43,673 B

6.4% smaller than original

smallest upstream per module · 46,660 B
gzip-918,734 B

1.6% smaller than original

smallest upstream per module · 19,045 B
Brotli-1116,953 B

1.6% smaller than original

smallest upstream per module · 17,234 B
Current LilScript versus minified original
Compiler objectiveLilScriptOriginal minifiedOriginal minifierDifference
Raw43,673 B46,660 Bsmallest upstream per module6.4% smaller
gzip-918,734 B19,045 Bsmallest upstream per module1.6% smaller
Brotli-1116,953 B17,234 Bsmallest upstream per module1.6% smaller

Each LilScript row comes from a separate compilation targeting that row’s objective. Raw is uncompressed JavaScript; gzip uses level 9; Brotli uses quality 11 and window 22. For each metric, the original is the smallest result among the minifiers below. No JavaScript minifier runs after LilScript.

Every artifact, measured with all three codecs
ArtifactRawgzip-9Brotli-11
LilScript · Raw objective43,673 B19,345 B17,426 B
LilScript · gzip-9 objective45,101 B18,734 B16,990 B
LilScript · Brotli-11 objective45,258 B18,872 B16,953 B
Original · PostHog’s build Rolldown 1.2.12 + Terser 5.51.246,987 B19,045 B17,234 B
Original · esbuild 0.28.267,055 B28,452 B25,707 B
Original · Oxc (Rolldown) Rolldown 1.2.1250,234 B19,991 B18,040 B

Seven submodules of posthog-js, each bundled from its TypeScript with everything it imports and compared on its own; the totals add them. Upstream: posthog-js@1.435.8. No external runtime imports. CSS, fonts, type declarations and source maps are outside these JavaScript sizes.

Measurements, hashes and settings ↗ · Commands and build receipts ↗

All seven submodules · speed · Chromium 139.0.7258.5

Speed in the browser.

Faster6 of 15warm workloads, interval entirely faster
No clear difference7 of 15interval includes zero
Slower2 of 15Exception capture · parse-stacks +2.5%, Feature flag responses · flags-v2-reads +1.4%
Import slower2 of 7Exception capture +0.20 ms, Metrics client +0.18 ms
LilScript (Brotli build) versus PostHog’s build, Chromium
ModuleWorkloadPostHog’s buildLilScriptTime95% intervalVerdict
Exception captureImportdynamic import from a fresh Blob URL: parse, compile, evaluate1.565 ms1.765 ms+11.9%+8.5% … +16.9%slower
Exception capturebuild-properties29 inputs through the properties builder: real Chromium errors with causes, an AggregateError, a DOMException, error and rejection events, strings, objects2.635 ms2.648 ms+0.5%−0.5% … +1.5%no clear difference
Exception captureparse-stacks11 Chrome, Firefox and Safari stack strings through the parser1.714 ms1.758 ms+2.5%+1.9% … +3.5%slower
Exception captureexception-steps150 exception steps into the 32 KB buffer0.955 ms0.915 ms−4.7%−5.9% … −3.5%faster
Browser, OS and device detectionImportdynamic import from a fresh Blob URL: parse, compile, evaluate1.280 ms1.245 ms−4.2%−6.6% … +0.2%no clear difference
Browser, OS and device detectioncorpusOS, browser, device, device type and version for the 606 user agents in posthog-js’s tests4.030 ms3.593 ms−11.3%−12.5% … −10.0%faster
Browser, OS and device detectiontraffic-mixthe same per-event sequence for 200 events from a modern browser mix0.921 ms0.782 ms−15.4%−15.7% … −14.6%faster
Autocapture DOM utilitiesImportdynamic import from a fresh Blob URL: parse, compile, evaluate1.540 ms1.560 ms+4.5%−0.9% … +7.8%no clear difference
Autocapture DOM utilitiesclick-pipeline43 clicks on a realistic app page through posthog-js’s autocapture flow, with the dead-click and rage-click checks11.825 ms11.685 ms−1.1%−2.7% … −0.0%faster
Autocapture DOM utilitiestext-scrubscrubbing page text, attributes and 12 network bodies0.537 ms0.540 ms+0.5%−2.3% … +3.0%no clear difference
Feature flag responsesImportdynamic import from a fresh Blob URL: parse, compile, evaluate1.098 ms1.127 ms+3.3%−4.0% … +9.9%no clear difference
Feature flag responsesflags-v2-readsa 64-flag /flags response handled as the client does: normalize, values, payloads, reads, overrides, the flag-called event0.521 ms0.532 ms+1.4%+0.5% … +2.5%slower
Feature flag responsesflags-v1-storagerebuilding stored flags in the older format0.172 ms0.153 ms−11.6%−12.4% … −7.8%faster
Metrics clientImportdynamic import from a fresh Blob URL: parse, compile, evaluate1.345 ms1.525 ms+16.6%+7.5% … +21.2%slower
Metrics clientrecord-drain1,000 samples (histograms, counters, gauges), then drainWindow()1.614 ms1.600 ms−0.8%−5.2% … +0.3%no clear difference
Metrics clientrecord-flush200 samples, then await flush()0.546 ms0.482 ms−11.0%−13.4% … −8.3%faster
UUIDv7 idsImportdynamic import from a fresh Blob URL: parse, compile, evaluate1.203 ms1.212 ms−3.1%−6.0% … +3.0%no clear difference
UUIDv7 idsgenerate1,000 uuidv7() calls0.782 ms0.786 ms+1.0%−0.2% … +1.9%no clear difference
UUIDv7 idstimestamp1,000 uuid7ToTimestampMs() calls0.271 ms0.274 ms+1.0%−1.4% … +2.8%no clear difference
Request compressionImportdynamic import from a fresh Blob URL: parse, compile, evaluate1.102 ms1.110 ms+1.8%−2.5% … +9.8%no clear difference
Request compressionevent-batcha 30-event batch (61 KB)2.414 ms2.412 ms+0.2%−1.7% … +1.3%no clear difference
Request compressionreplay-snapshota 563 KB replay snapshot14.260 ms14.233 ms−0.1%−0.6% … +0.4%no clear difference

Each sample is a fresh browser context on a local, cross-origin-isolated page; PostHog’s build and LilScript’s alternate in ABBA order, 40 samples per module. A time is the median of 15 repetitions after 5 untimed ones; the change is the median of the paired differences with a 95% bootstrap interval, and a verdict needs that interval to exclude zero. Both builds first run the same inputs and must give identical output. A control — PostHog’s build against an identical copy of itself — flagged 3 of 37 rows, so changes of one or two percent are within noise. Import is slower where a module defines most of its functions as top-level arrows, which V8 parses more slowly in module code.

All seven submodules · same machine · sequential builds

Build time.

Build wall time on the same machine
Output objectiveLilScript compilationOriginal bundling + minificationOriginal minifier
Raw8.05 s0.712 ssmallest upstream per module
gzip-912.95 s0.870 ssmallest upstream per module
Brotli-1126.50 s0.870 ssmallest upstream per module

One fresh output build per objective and minifier, run sequentially. LilScript compilation includes optimization and objective scoring with persistent caches disabled and one worker. Original time includes Node startup, esbuild bundling of installed upstream ESM, and the named minifier. It excludes building the upstream package from its original TypeScript sources. Dependency installation, tests and final file compression are excluded on both sides. These are observations on a shared machine, not a build-speed guarantee.

AMD EPYC 7763 64-Core Processor · 8 logical CPUs · 15.6 GiB RAM · Linux 7.0.0-1014-azure · Node v20.19.0. Measured 2026-10-04. Exact commands and compiler identity ↗

The compiled runtime, in the browser

Live
lab.

Left is the input. Right is what the selected build returns — LilScript’s or PostHog’s — and whether the other build returns the same. Both builds of the module load in this page.

The lab runs with JavaScript enabled.

posthog-js@1.435.8 · LilScript d8f79ed5

Same behaviour.
Smaller.

Not affiliated with PostHog. posthog-js is MIT-licensed; its license and notices ship with this site. Upstream tests are counted as the behaviour gate counts them: every test that passes against PostHog’s bundled, mangled build must pass against LilScript’s.