Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

FlexViz

Interactive visualization at scale.
Python  ·  Polars-native  ·  stateless server  ·  Rust-accelerated  ·  AI-native

CI status CodSpeed benchmarks PyPI version Supported Python versions Apache-2.0 license

Documentation · Live demo · Benchmarks · Agents


FlexViz is a visualization library for exploring datasets that are too big for conventional Python dashboarding tools.
Charts stay interactive (zoom, pan, cross-filter) at 100M+ rows because every interaction is answered by lazy Polars aggregations and Rust kernels instead of by shipping raw data to the browser.
The same engine serves a coding agent: it builds the dashboard, hands you the URL, and reads back what you zoomed and brushed. You explore the data together, and neither of you loads it.

Cross-filter demo: brushing a range on a 100M-point line chart re-aggregates the linked histogram

Brush one chart and every linked chart re-aggregates against the filtered set. Try it yourself on 2 x 100M rows in the live demo.

Install

pip install flexviz

The Rust kernels arrive as a prebuilt wheel (flexviz-polars) on Linux (x86_64, aarch64), macOS (Intel and Apple silicon), and Windows (x64). Any other platform builds them from source and needs a Rust toolchain.

Quickstart

Run this after pip install flexviz or uv add flexviz. It generates 10 million rows and opens two linked figures.

import numpy as np
import polars as pl

from flexviz import Dashboard

n = 10_000_000
value = np.sin(np.arange(n) / 5e4) + np.random.default_rng(0).standard_normal(n) * 0.05
value[6_000_000:6_050_000] += 3.0  # a 0.5% burst
ts = pl.datetime(2024, 1, 1) + pl.duration(milliseconds=pl.int_range(n) * 10)
df = pl.select(timestamp=ts, value=pl.Series(value))

dash = Dashboard(df, cache=True)
dash.add_figure(title="value").add_line(x="timestamp", y="value", n_points=2000)
dash.add_figure(title="distribution").add_histogram(x="value", bins=60)
dash.show()

Try:

  • Zoom the line near 16:40 on Jan 1 to see the shape of the burst.
  • Brush the histogram above value 2. Only the burst remains in the line.

The same script lives at examples/quickstart_10m.py.

Your own data

import polars as pl
from flexviz import Dashboard

lf = pl.scan_parquet("readings.parquet")  # 100M rows, stays lazy

dash = Dashboard(lf)
dash.add_figure().add_line(x="timestamp", y="value")
dash.add_figure().add_histogram(x="value", bins=50)
dash.show()  # brush one chart to cross-filter the other

The LazyFrame stays lazy. FlexViz loads nothing until a chart needs it.

Outside a notebook, show() blocks until Ctrl-C. Pass block=False to return at once.

Guides and the full API reference live at docs.flexviz.tech.

Agents

FlexViz is built as an AI-native tool: a coding agent hands you a live dashboard instead of a static plot, on which you can both co-explore the full data at scale.

Today, agents can already write plotting code. The trouble starts after that. Plotting libraries cannot draw 100M points, so the figure comes out slow, unreadable, or not at all. What does arrive is a static image. You cannot zoom into the part that looks odd. And the agent cannot see what you did with the figure, short of a screenshot and a guess at the pixels.

FlexViz removes all three limits. The agent writes a spec instead of plotting code. The engine answers every zoom, pan, and cross-filter against the raw rows, so the chart stays interactive at full size. And your interactions travel back as a spec, not as pixels: the agent only needs to reads your exact viewport and selections to know what your looking at.

The wheel ships an Agent Skill that teaches your agent the workflow:

flexviz skill install          # into .agents/skills/ and .claude/skills/
flexviz skill install --user   # or once under $HOME, for every project

Claude Code and Codex can install the skill as a plugin instead, before the package is in the project:

/plugin marketplace add flex-analytics/flexviz
/plugin install flexviz@flex-analytics
codex plugin marketplace add flex-analytics/flexviz
codex plugin add flexviz@flex-analytics

Then ask it to explore readings.parquet. It reads the schema, serves the file, and gives you the URL.

From there you explore together. You zoom and brush. The agent reads your viewport and selections back. It can discuss what you have in front of you, compute statistics on exactly the rows you brushed, and build a new view when you ask for one. With browser tooling it can even drive the dashboard itself.

See the agent guide.

Features

FlexViz is a library, not a (cloud) service. The dashboard server runs where your data lives, on your laptop or in your own infra, and rows never leave it.

  • 10 trace types: line, histogram, box, bar, pie, treemap, 2D histogram, correlation heatmap, geo 2D histogram, geo line.
  • Bring any DataFrame: Polars DataFrames/LazyFrames, pandas DataFrames, and PyArrow tables.
  • Interactivity:
    • Zoom re-aggregation: zooming recomputes a figure for its viewport, so a line re-downsamples and a histogram re-bins; detail appears as you dive.
    • Native cross-filtering: brush or click one figure to filter the others, either replacing their view (update mode) or drawing the filtered aggregate on top of the totals (overlay mode).
    • Linked hover: hovering one figure highlights the matching position in every figure that shares its columns, fully client-side.
  • Grouped traces: group_by splits a trace into per-category series with stable colors, computed in a single grouped Polars query.
  • Shareable URLs: every view (viewport, selections, cross-filter mode, and layout) encodes into a single URL. Send the link and a teammate opens the exact live view; the server stores nothing.
  • Draggable dashboard grid: rearrange and resize panels in the browser and lock the layout when it's done; the arrangement also travels with the URL.
  • Embeddable: mounts into an existing FastAPI app via mount_into().

Why it scales

  • Polars-native. Data stays a lazy LazyFrame until the last moment. In-memory frames and Parquet-backed sources both work. That laziness is what gives out-of-core support: sources larger than RAM stream rather than load, so peak memory stays flat as the row count grows instead of scaling with it. A 1B-row, 24 GB Parquet source drives a line and histogram dashboard, including zoom and cross-filter, in under 400 MB of resident memory. make test-ooc asserts that flatness per trace. Box plots are the exception, because Polars computes quantiles in memory.
  • Rust kernels. Min/max line downsampling and fixed-bin histogram/heatmap binning run as parallel Polars expression plugins (flexviz_polars), at memory-bandwidth speed.
  • Aggregates over the wire. The browser receives a few thousand points per trace, never the raw rows
  • Cube live-brushing. Dragging a brush is served client-side from a small pre-aggregated cube: zero server round-trips during the drag.
  • Stateless server. The client owns all interaction state and every request carries the complete dashboard spec. No sessions, no server affinity, and shareable dashboard URLs are a free feature.
  • Renderer-agnostic core. Specs, traces, and the engine know nothing about the renderer; a thin adapter maps updates onto Plotly.js, the default renderer.

Benchmarks

Time to render 1 billion points per chart: 5 traces × 200M rows from an in-memory frame, clocked browser-side from the request to painted pixels (median of 5 warm repeats). Each engine renders its own native chart: the line runs against Datashader and Mosaic, the histogram against Vaex and Mosaic, because neither of those tools has the other chart.

Time to first render at 200M rows and 5 traces: FlexViz against Datashader, Vaex, and Mosaic, fastest in both the line and histogram panels. Latest numbers at flexviz.tech/benchmarks.

Peak backend memory stays at ~25 MB from 1M to 200M rows: FlexViz aggregates the caller's frame zero-copy.

Charts for the full matrix (1M–200M rows, 1/2/5 traces, in-memory and Parquet-backed) are at flexviz.tech/benchmarks; the harness, correctness gates, per-trial results, and caveats live in flexviz-benchmarks.

Development

git clone https://github.com/flex-analytics/flexviz
cd flexviz
uv sync              # installs deps and builds the Rust plugin
make test

The Rust plugin builds automatically; the toolchain is pinned in rust-toolchain.toml.

See the compatibility policy in the changelog.
Architecture.md is the design source of truth.

Acknowledgements

FlexViz builds on ideas from projects that pioneered server-side aggregation for interactive visualization:

  • Mosaic: scalable linked views over DuckDB, from the UW Interactive Data Lab.
  • VegaFusion: server-side acceleration for Vega and Altair.
  • Falcon: cross-filter prefetching with data cubes.

License

Apache-2.0 © 2026 Flex Analytics BV

Release files for flexviz 0.1.0b4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for flexviz 0.1.0b4
File Size Uploaded
flexviz-0.1.0b4.tar.gz 696.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for flexviz 0.1.0b4
File Interpreter ABI Platform
flexviz-0.1.0b4-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / flexviz-0.1.0b4.tar.gz

Download URL flexviz-0.1.0b4.tar.gz
Size 696.8 kB
Tags Source
SHA-256 checksum
How to use checksums
d8f1b0e6ae58dbf313acae11dd6ef4269a55d372105aa8334ef92762b608217d
BLAKE2b-256 checksum
How to use checksums
2d4ff7c7ef81cd571ab989c9b4f7db4c1fb65f26abfbec21a7a926016e494d0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / flexviz-0.1.0b4-py3-none-any.whl

Download URL flexviz-0.1.0b4-py3-none-any.whl
Size 329.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
67ae50324853b0b3fca037c378c63783a914819b6ba17dfef79addad1bc0f3b0
BLAKE2b-256 checksum
How to use checksums
8f4107bb12021177448ee7566734458989da1cc10bbadaf22716d20083c4826e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page