Skip to content

Binary Data Transport

For datasets with 100k+ rows, binary transport bypasses JSON serialization entirely: data crosses the Python→JS boundary as packed typed arrays and feeds deck.gl's native data.attributes format straight to the GPU.

Measured at 200k polygons:

Mode Serialization Payload
JSON 1,167 ms 62 MB
Binary 39 ms 14.5 MB 30× faster, 4.3× smaller

Supported on: ScatterplotLayer, PolygonLayer, PathLayer, ArcLayer, LineLayer, ColumnLayer, PointCloudLayer.

Simple: use_binary=True

layer = dgl.ScatterplotLayer(
    data=large_df.to_dict("records"),
    get_position=["lon", "lat"],
    get_fill_color="color",     # per-row column
    get_radius="radius",
    use_binary=True,
)

Column accessors (and ColorScale/callable color accessors) are resolved in Python and packed into the buffer; constant props stay in the spec.

Note

The measured speedups above apply to the pre-built numpy path below. use_binary=True over a list of dicts still iterates rows in Python to build the arrays — much smaller payload, but packing time grows with row count.

Fastest: pre-built numpy arrays

Zero per-row iteration — hand the packer ready-made arrays:

import numpy as np
from deckgl_marimo import pack_binary

positions = np.column_stack([lons, lats]).astype(np.float32)
colors = np.asarray(color_data, dtype=np.uint8)     # (n, 4)

layer = dgl.ScatterplotLayer(radius_min_pixels=2, use_binary=True)
spec = layer.to_spec()

meta, buf = pack_binary(
    n=len(positions),
    attributes={
        "getPosition": (positions, "float32", 2),
        "getFillColor": (colors, "uint8", 4),
    },
)
meta["id"] = spec["id"]

deck_map.binary_metadata = {"layers": [meta]}
deck_map.binary_data = buf
deck_map.layer_specs = [spec]

For polygons there is pack_polygon_binary (handles vertex flattening and startIndices for variable-length geometry).

Layers can also take array dicts directly

Binary-capable layers accept a dict of pre-built arrays as data, which routes through the fast path automatically:

layer = dgl.ScatterplotLayer(
    data={"positions": positions, "colors": colors, "radii": radii},
    use_binary=True,
)
deck_map.set_layers([layer])

Fast-path keys per layer: positions/colors/radii (Scatterplot), source_positions/target_positions/source_colors/target_colors (Arc), positions/colors/elevations (Column), positions/colors/normals (PointCloud), path_coords/start_indices/ colors (Path), polygon_coords/start_indices/colors (Polygon).

Picking and tooltips still work

deck.gl picks binary layers by index; the widget back-fills the picked row into click_info/hover_info on the Python side, and a tooltip column is pre-packed for hover tooltips. See Picking & Events.