Build1 distinct publisher3 min readUpdated
A Leaflet layer moves Mercator projection into a vertex shader and resolves clicks by reading one pixel from a hidden buffer. Its author's own numbers say the bill arrives at moveend.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The benchmark figure worth attention is the one that refuses to scale. Dropping icons from 38px to 8px shrinks the drawn area per marker by a factor of about 22.6, but the full redraw of a million visible markers only falls from roughly 200 ms to roughly 50 ms, a factor of four [12][1]. Convert those two runs into fill throughput and they look like different machines: about 7.2 gigapixels per second in the large-icon case, about 1.28 in the small-icon case [2]. The big-icon run is fill-bound, which is what the author says the cost model predicts, since redraw scales with visible markers times icon area [13]. The small-icon run is not. At 8px you are paying per-marker and per-draw overhead, so the obvious lever, shrink the icons at low zoom, stops returning after the first pull.
That matters because of where the redraw lands. Panning touches no buffer at all: the canvas rides along under a CSS transform and no JavaScript runs per frame, with a single redraw deferred to `moveend` [5]. The display pass itself is reported at well under a millisecond per frame with a million points on a mid-range GPU [11]. So the drag is genuinely free, and then the settle costs about 12 frame budgets at 60 Hz [3]. The freeze has not been removed, it has been moved to the moment the user stops moving, which is also the moment they are looking hardest at the result.
The picking design is the part that reads as engineering rather than demo. Each marker is drawn into an invisible framebuffer in a unique encoded colour; a pointer event reads back one pixel and decodes it, so hit-testing is one `readPixels` regardless of dataset size [6]. Two details carry the weight. Pixels and the decode table are published atomically from the same frame, so a pointer event never pairs new pixels with a stale table [8]. And during a drag or zoom animation, when the published frame no longer matches the viewport, picking returns "unavailable" rather than resolving the wrong marker, recovering at `moveend` [9]. That is a deliberate trade of availability for correctness. A click in the tail of a pan gets nothing, which is a better failure than a popup for the wrong plane.
The boundaries are stated rather than buried. Projection is hardcoded to EPSG:3857 and other CRS values fail fast at `addTo` [15]. All markers share one texture, and the author's advice for a handful of custom interactive markers is to keep using `L.Marker` [17]. WebGL 1.0 with hardware acceleration is a hard requirement [16]. There is no LOD policy in the box, only `setIconSize` and the expectation that you wire it to zoom yourself [14]. Every timing here comes from the library's own author in a single post [12], so treat the millisecond figures as a shape, not a spec.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
Leaflet's default markers are DOM elements, and every marker costs DOM nodes, layout, event listeners and paint.
Around a few thousand markers most browsers start to feel it, and at a hundred thousand the map becomes unusable.
Measured by the author with 1,000,000 visible markers on one canvas, a full redraw took roughly 200 ms at 38px icons and roughly 50 ms at 8px icons.
The real cost is the one full redraw at the end of a gesture, and it scales with visible markers times icon area.
Leaflet offers two native marker paths, neither designed for big data on a map; DOM nodes and CPU-side redraws are the wrong tool at six digits of points.
leaflet-webgl-markers renders every marker from a single WebGL canvas, with lat/lng held in a vertex buffer; a million markers is a few tens of megabytes of buffer rather than a million elements.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Detailed but single-source and self-reported
The mechanism claims are specific and internally coherent — vertex-buffer storage, shader-side Mercator, CSS-transform panning, colour-encoded pick pass with atomic publish and mid-gesture refusal — and the author volunteers concrete numbers and hard limitations. But the entire cluster is one post authored by the library's maintainer, with no independent reproduction, no stated hardware or methodology behind the timings, and no third-party review of the picking guarantees.
No adoption signal beyond availability
The cluster documents that the package is published on npm with a repository and an author-built demo, but contains no downloads, dependents, stars, production deployments or third-party usage disclosures. Availability is not adoption, and nothing in the supplied material lets adoption be scored.
Headline outruns the author's own numbers, but only modestly
'Rendering 1 Million Markers' and 'million markers without freezing' read stronger than the disclosed behaviour: interaction stays smooth, yet each gesture ends in a redraw of roughly 200 ms at 38px icons — about twelve 60 Hz frames — and shrinking icons 22.6x in area recovers only 4x of that time, so the escape hatch is weaker than it looks. The gap stays small because the post itself labels this 'the honest trade-off' and enumerates CRS, WebGL, texture and accessibility limits; the remaining overstatement is that all numbers are self-reported and unverified, and no adoption evidence backs the implied production readiness.
Author promoting own package
The post is written by the library's author, links its npm page, GitHub repository and hosted demo, and closes by soliciting reader questions in the comments. Every performance figure is generated and reported by the party whose project benefits from it, with no independent verification in the cluster. Mitigating factor: the author publishes an explicit limitations list and the unflattering moveend cost rather than suppressing them.
Mechanism credible, magnitude unverified
Confidence in the architecture description is fairly high: it is specific, standard practice for GPU picking, and consistent with the disclosed limits (EPSG:3857 hardcoding, WebGL 1.0 requirement, single texture). Confidence in the performance envelope and in real-world durability is low, because a single self-interested source supplies all numbers, no methodology is published, and there is no adoption or maintenance evidence.
build
Punctuation is a three-way classification, not a model call1 distinct publisher
build
A build step instead of a backend: 1,025 records, 8 locales, no runtime API1 distinct publisher
security
Two Artifactory flaws poisoned metadata, not artifacts, and that was enough to break a shared cache1 distinct publisher
build
Allow-list the closed set, block-list the open one: 193 thin geo pages, one gate1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 23, 2026