bokeh/bokeh

Interactive Data Visualization in the browser, from Python

20,380 stars TypeScript 7 components

10 hidden assumptions · 7-stage pipeline · 7 components

Like any codebase, this library makes assumptions it never checks — most are routine. The ones worth your attention are below.

Generates interactive browser visualizations from Python using dual-runtime architecture

Data starts in Python as pandas DataFrames or dicts, gets serialized to JSON with binary buffers for large arrays, transmitted to browser where it's reconstructed as typed arrays. GlyphViews read these arrays, apply coordinate transformations through Scale objects, and render visual marks to HTML5 canvas. User interactions trigger hit tests that update Selection objects, which propagate back through the system to highlight related data points.

Under the hood, the system uses 3 feedback loops, 3 data pools, 3 control points to manage its runtime behavior.

A 7-component library. 2212 files analyzed. Data flows through 7 distinct pipeline stages.

Hidden Assumptions

Most of what this code assumes is routine. These 3 are the ones most likely to cause trouble here. The rest are minor; they're under "Show everything".

Worth your attention first

If a data source contains a column with incompatible data (like objects that Array.from() creates weird arrays from), get_array returns T[] but with wrong element types, causing type-unsafe operations downstream in GlyphView rendering

Worth your attention first

If hit testing occurs before rendering completes, accessing this.index throws 'index_data() wasn't called', breaking selection and interaction features silently until user clicks

Worth your attention first

If multiple bokeh plots try to use different WebGL contexts, they share the same ReglWrapper instance tied to the first context, causing rendering artifacts or crashes when switching between plots

Show everything (7 more)
Environment

WebGL extensions ['ANGLE_instanced_arrays', 'EXT_blend_minmax', 'OES_element_index_uint'] will be available in the browser context, but only checks if WebGL context creation succeeds

If this fails: If any required extension is missing, regl initialization may fail or glyphs render incorrectly without clear error messages, causing fallback to Canvas2D without user awareness

bokehjs/src/lib/models/glyphs/webgl/regl_wrap.ts:constructor
Scale

Factor arrays will contain reasonable numbers of unique string values (hundreds, not millions), but no bounds checking exists on the factors parameter length

If this fails: With millions of categorical factors, the mapping creation becomes O(n²) in memory and extremely slow, potentially causing browser tabs to hang or crash during coordinate transformation

bokehjs/src/lib/models/ranges/factor_range.ts:map_one_level
Temporal

Source files on disk won't change between dependency resolution and compilation phases, but no file locking or timestamp validation occurs

If this fails: If files are modified during the build process (common in watch mode), the compiler may use stale dependency graphs with fresh file contents, producing inconsistent builds or missing imports

bokehjs/src/compiler/build.ts:compiler host and file system operations
Contract

The SelectionManager will coordinate with GlyphRenderer views that have been properly initialized and connected through signals, but no validation ensures the renderer-datasource binding

If this fails: If a GlyphRenderer is created but not properly connected to its data source's selection signals, selection highlighting breaks—users can select points but visual feedback disappears, making multi-plot dashboards unusable

bokehjs/src/lib/models/sources/columnar_data_source.ts:selection_manager
Ordering

connect_signals() will be called after constructor but before any property changes or event callbacks are triggered, following a strict initialization order

If this fails: If properties are modified before connect_signals() runs, the _update_property_callbacks() won't be set up, causing js_property_callbacks to silently fail and custom JavaScript event handlers to never execute

bokehjs/src/lib/model.ts:connect_signals lifecycle
Domain

Factor tuples will consistently have the same nesting level throughout a single dataset (all L1Factor, all L2Factor, or all L3Factor), but no runtime validation enforces homogeneity

If this fails: Mixing factor levels like [['A'], ['B', 'C']] causes coordinate mapping to fail unpredictably—some categorical points render in wrong positions or disappear entirely from plots

bokehjs/src/lib/models/ranges/factor_range.ts:FactorSeq type system
Contract

Input JSON from stdin or argv.file will conform to the expected schema with 'code', 'lang', 'file', and 'bokehjs_dir' fields, but only validates file existence not content structure

If this fails: Malformed compilation requests cause JSON.parse() to throw or compile_and_resolve_deps() to fail with cryptic errors, breaking bokeh server's dynamic extension loading without clear error messages

bokehjs/src/compiler/main.ts:compile function

Open the standalone hidden-assumptions report for bokeh →

How Data Flows Through the System

Data starts in Python as pandas DataFrames or dicts, gets serialized to JSON with binary buffers for large arrays, transmitted to browser where it's reconstructed as typed arrays. GlyphViews read these arrays, apply coordinate transformations through Scale objects, and render visual marks to HTML5 canvas. User interactions trigger hit tests that update Selection objects, which propagate back through the system to highlight related data points.

  1. Python model creation — User creates plots in Python using bokeh.plotting API, defining data sources, glyphs, layouts, and styling that get registered as Model instances with property validation
  2. JSON serialization — Python models serialize to JSON using bokeh.core.serialization.Serialized, with large arrays extracted to binary buffers to avoid JSON parsing overhead [Python Model objects → Serialized]
  3. Browser transmission — JSON model definition gets embedded in HTML template or transmitted over WebSocket connection to Bokeh server, binary buffers sent as separate ArrayBuffer messages [Serialized → Raw JSON + buffers]
  4. JavaScript model reconstruction — Browser reconstructs JavaScript Model instances from JSON using HasProps property system, binary buffers become typed arrays (Float32Array, Int32Array) for efficient processing [Raw JSON + buffers → ColumnarDataSource]
  5. Coordinate transformation — GlyphView.compute_layout transforms data coordinates to screen pixels using Scale objects (LinearScale, LogScale, FactorRange), handling categorical and continuous axes [ColumnarDataSource → Screen coordinates]
  6. Canvas rendering — GlyphView.render draws visual marks to HTML5 Canvas2D context or WebGL through ReglWrapper, batching operations for performance with large datasets [Screen coordinates → Rendered pixels]
  7. Interaction handling — User clicks/hovers trigger GlyphView.hit_test which uses spatial indexing to find data points under cursor, updates Selection objects with indices of selected items [Mouse events → Selection]

Data Models

The data structures that flow between stages — the contracts that hold the system together.

ColumnarDataSource bokehjs/src/lib/models/sources/columnar_data_source.ts
Dict with column names mapping to Arrayable<T> (typed arrays or regular arrays), plus selection state and default_values
Created from Python pandas DataFrame or dict, transmitted as JSON, reconstructed as JavaScript object with typed arrays for efficient rendering
GlyphView bokehjs/src/lib/models/glyphs/glyph.ts
DOM component with visuals properties, spatial index, data arrays, and optional WebGL renderer
Instantiated from JSON model, computes screen coordinates from data coordinates, renders to canvas on each frame, handles mouse/touch events
Selection bokehjs/src/lib/models/selections/selection.ts
Object with indices: OpaqueIndices, line_indices: OpaqueIndices, multiline_indices: MultiIndices, image_indices: ImageIndices arrays
Created empty, populated during hit testing, transmitted between client/server for linked selections, merged using set operations
Serialized src/bokeh/core/serialization.py
Dataclass with content: T and buffers: list[Buffer] for binary data
Python models serialize to JSON with optional binary buffers for large arrays, transmitted over WebSocket or embedded in HTML, deserialized to reconstruct JavaScript models

System Behavior

How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.

Data Pools

Data column arrays (in-memory)
Column-oriented data storage using typed arrays (Float32Array, Int32Array) for efficient bulk operations and WebGL compatibility
Spatial index (index)
R-tree spatial index built during rendering to accelerate hit testing and selection operations on large datasets
WebGL buffer cache (buffer)
GPU memory buffers that cache vertex data and shader programs for high-performance rendering of scatter plots and lines

Feedback Loops

Delays

Control Points

Technology Stack

TypeScript (runtime)
Primary language for browser-side rendering engine and interaction handling
Python (runtime)
High-level API for plot construction and data binding, server runtime
HTML5 Canvas (runtime)
2D graphics rendering target for all visualizations
WebGL/Regl (compute)
GPU-accelerated rendering for large datasets through shader-based pipeline
Tornado (infra)
WebSocket server for live data updates and bidirectional communication
NumPy (library)
Efficient array operations and data type handling in Python layer
Node.js toolchain (build)
TypeScript compilation, bundling, and development workflow automation

Key Components

Explore the interactive analysis

See the full architecture map, data flow, and code patterns visualization.

Analyze on CodeSea

Related Library Repositories

Frequently Asked Questions

What is bokeh used for?

Generates interactive browser visualizations from Python using dual-runtime architecture bokeh/bokeh is a 7-component library written in TypeScript. Data flows through 7 distinct pipeline stages. The codebase contains 2212 files.

How is bokeh architected?

bokeh is organized into 4 architecture layers: Python API Layer, Serialization Bridge, TypeScript Compiler System, Browser Rendering Engine. Data flows through 7 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.

How does data flow through bokeh?

Data moves through 7 stages: Python model creation → JSON serialization → Browser transmission → JavaScript model reconstruction → Coordinate transformation → .... Data starts in Python as pandas DataFrames or dicts, gets serialized to JSON with binary buffers for large arrays, transmitted to browser where it's reconstructed as typed arrays. GlyphViews read these arrays, apply coordinate transformations through Scale objects, and render visual marks to HTML5 canvas. User interactions trigger hit tests that update Selection objects, which propagate back through the system to highlight related data points. This pipeline design reflects a complex multi-stage processing system.

What technologies does bokeh use?

The core stack includes TypeScript (Primary language for browser-side rendering engine and interaction handling), Python (High-level API for plot construction and data binding, server runtime), HTML5 Canvas (2D graphics rendering target for all visualizations), WebGL/Regl (GPU-accelerated rendering for large datasets through shader-based pipeline), Tornado (WebSocket server for live data updates and bidirectional communication), NumPy (Efficient array operations and data type handling in Python layer), and 1 more. A focused set of dependencies that keeps the build manageable.

What system dynamics does bokeh have?

bokeh exhibits 3 data pools (Data column arrays, Spatial index), 3 feedback loops, 3 control points, 3 delays. The feedback loops handle self-correction and self-correction. These runtime behaviors shape how the system responds to load, failures, and configuration changes.

What design patterns does bokeh use?

4 design patterns detected: Dual-runtime architecture, Property-driven reactive system, Pluggable rendering backends, Spatial indexing for interactions.

Analyzed on April 20, 2026 by CodeSea. Written by .