getredash/redash
Make Your Company Data Driven. Connect to any data source, easily visualize, dashboard and share your data.
Connects to multiple data sources, lets users write SQL queries, creates visualizations and dashboards
Users write SQL queries in the browser-based editor, which extracts parameters and validates syntax. When executed, queries are sent to the backend where the appropriate query runner connects to the data source, executes the query, and stores results in cache. Results flow to visualization components that render charts and tables, which can be organized into dashboards with filtering and real-time updates.
Under the hood, the system uses 4 feedback loops, 4 data pools, 5 control points to manage its runtime behavior.
A 10-component fullstack. 860 files analyzed. Data flows through 7 distinct pipeline stages.
How Data Flows Through the System
Users write SQL queries in the browser-based editor, which extracts parameters and validates syntax. When executed, queries are sent to the backend where the appropriate query runner connects to the data source, executes the query, and stores results in cache. Results flow to visualization components that render charts and tables, which can be organized into dashboards with filtering and real-time updates.
- Query Composition — Users write SQL in QueryEditor component with syntax highlighting and schema browser, while ParameterExtractor identifies mustache-style parameters like {{date_range}} [DataSource → Query] (config: x-redash-environment.REDASH_HOST)
- Parameter Resolution — Parameter.js normalizes parameter values from dashboard filters or user input, validates types, and prepares substitution values for query execution [Parameter → Parameter]
- Query Execution — QueryExecutor.execute_query() selects the appropriate query runner from the registry, substitutes parameters, executes against the data source, and handles timeouts and retries [Query → QueryResult] (config: x-redash-environment.REDASH_DATABASE_URL, x-redash-environment.REDASH_REDIS_URL)
- Result Caching — QueryResult.store_result() saves execution results in PostgreSQL with TTL-based expiration, indexed by query hash for cache hits on identical queries [QueryResult → QueryResult] (config: x-redash-environment.REDASH_REDIS_URL)
- Visualization Rendering — VisualizationRenderer components in viz-lib transform QueryResult.data into chart configurations for D3, Plotly, or custom components based on Visualization.options [QueryResult → Visualization]
- Dashboard Assembly — DashboardGrid loads all widgets, executes their queries if not cached, renders visualizations, and arranges them according to Dashboard.layout grid positions [Dashboard → Dashboard] (config: x-redash-environment.REDASH_HOST)
- Alert Evaluation — AlertEvaluator checks QueryResult values against Alert conditions, triggers notifications via email or Slack when thresholds are exceeded [QueryResult → Alert Notifications] (config: x-redash-environment.REDASH_MAIL_DEFAULT_SENDER)
Data Models
The data structures that flow between stages — the contracts that hold the system together.
redash/models/queries.pySQLAlchemy model with id: int, name: str, description: str, query: str, data_source_id: int, user_id: int, is_draft: bool, is_archived: bool, schedule: dict, options: dict containing parameters
Created by users through the query editor, executed against data sources, results cached, and referenced by dashboard widgets
redash/models/query_results.pySQLAlchemy model with id: int, query_hash: str, query: str, data: JSON blob containing columns array and rows array, retrieved_at: datetime, runtime: float
Generated when queries execute, stored in cache with TTL, and consumed by visualizations to render charts
redash/models/dashboards.pySQLAlchemy model with id: int, name: str, slug: str, user_id: int, layout: JSON array of widget positions and sizes, is_archived: bool, is_draft: bool, tags: array
Created by users, populated with widgets that reference queries and visualizations, with grid layout stored as JSON
redash/models/data_sources.pySQLAlchemy model with id: int, name: str, type: str, options: JSON dict containing connection parameters like host, port, database, credentials, queue_name: str, scheduled_queue_name: str
Configured by admins with connection details, used by query runners to execute queries, and referenced in query metadata
client/app/services/parameters/Parameter.jsJavaScript class with title: str, name: str, type: str, global: bool, value: any, normalizedValue: any, locals: array of parameter references
Extracted from query text using mustache syntax, rendered as form inputs, values propagated to child widgets and queries
redash/models/visualizations.pySQLAlchemy model with id: int, type: str (chart, table, counter, etc), name: str, description: str, options: JSON dict with chart-specific config like axes, colors, grouping
Created when users choose chart types, configured with visualization-specific options, and rendered using query results
Hidden Assumptions
Things this code relies on but never validates. These are the things that cause silent failures when the system changes.
Assumes DOM element with id 'application-root' exists in the HTML document when the script loads
If this fails: React app fails to mount, throws 'Cannot read property of null' error and entire UI is broken
client/app/index.js:ReactDOM.render
Extensions in extensions/ directory must have init() function that returns something meaningful, but only checks isFunction and f.init existence
If this fails: Extension init() methods may fail or return unexpected values causing silent initialization failures or undefined behavior in registered extensions
client/app/config/index.js:registerExtensions
Extensions directory exists and contains valid JavaScript modules matching the regex pattern, no validation of extension structure
If this fails: If extensions directory is missing or contains malformed JS files, require.context() throws runtime errors breaking app initialization
client/app/config/index.js:require.context
Data source types like 'databricks' and 'databricks_internal' match exactly with DataSource.type field from the backend
If this fails: If backend returns different type strings or casing, wrong schema browser renders (default SchemaBrowser instead of DatabricksSchemaBrowser) causing missing features
client/app/components/queries/editor-components/index.js:registerEditorComponent
All images referenced by require.context exist and are readable at build time, no runtime fallback handling
If this fails: Missing image files cause build failures or broken image links in production, but app continues with missing assets
client/app/config/index.js:requireImages
Import order matters - pages must register before extensions to allow extensions to override routes, but this dependency is not enforced
If this fails: If import order changes, extensions may fail to override intended routes leading to wrong page components loading for specific paths
client/app/config/index.js:module imports
Moment.js locale 'en' exists and supports relativeTime configuration object with these specific keys
If this fails: If moment.js version changes or locale structure differs, relative time formatting silently falls back to defaults potentially showing inconsistent time formats
client/app/config/index.js:moment.updateLocale
Widget components (VisualizationWidget, TextboxWidget, RestrictedWidget) implement compatible interfaces expected by dashboard grid layout system
If this fails: If widget components don't match expected props interface, dashboard grid fails to render widgets or passes wrong props causing widget crashes
client/app/components/dashboards/dashboard-widget/index.js:exports
Avatar.svg file exists in assets/images directory and is accessible during build process
If this fails: Build fails if avatar.svg is missing, or users see broken default avatar images throughout the application
client/app/config/index.js:@/assets/images/avatar.svg
All form field components (AceEditorField, CheckboxField, etc.) implement consistent field interface with props like value, onChange, error
If this fails: Dynamic forms break if any field component has incompatible interface - form validation fails or field values don't update properly
client/app/components/dynamic-form/fields/index.js:field exports
System Behavior
How the system operates at runtime — where data accumulates, what loops, what waits, and what controls what.
Data Pools
PostgreSQL table storing query execution results with TTL for cache invalidation
User sessions, rate limiting counters, and temporary query execution state
React component state for dashboard widgets, parameter values, and UI interactions
Celery task queue for background query execution and scheduled refreshes
Feedback Loops
- Parameter Propagation (recursive, reinforcing) — Trigger: Dashboard parameter change. Action: Parameter.updateLocals() propagates values to all child widgets and re-executes affected queries. Exit: All dependent queries complete.
- Query Auto-refresh (polling, reinforcing) — Trigger: Query.schedule configuration. Action: Celery periodic task re-executes queries and updates cached results. Exit: Schedule disabled or query deleted.
- Alert Monitoring (polling, balancing) — Trigger: Alert.query schedule. Action: AlertEvaluator checks query results against thresholds and sends notifications. Exit: Alert disabled or condition no longer met.
- Cache Invalidation (cache-invalidation, balancing) — Trigger: Query execution or TTL expiry. Action: QueryResult.get_latest() checks cache freshness and triggers re-execution if stale. Exit: Fresh result found or new result cached.
Delays
- Query Execution Timeout (async-processing, ~30s default) — Long-running queries are cancelled to prevent resource exhaustion
- Result Cache TTL (cache-ttl, ~1 hour default) — Stale data served until cache expires and query re-executes
- Dashboard Refresh (scheduled-job, ~varies by query schedule) — Dashboard widgets show loading state while background queries execute
- Parameter Debounce (rate-limit, ~300ms) — Parameter changes batched to prevent excessive query re-execution
Control Points
- Query Timeout (threshold) — Controls: Maximum execution time before queries are cancelled. Default: 30 seconds
- Cache TTL (threshold) — Controls: How long query results remain fresh before re-execution. Default: 3600 seconds
- Rate Limiting (rate-limit) — Controls: Maximum API requests per user per time window. Default: x-redash-environment.REDASH_RATELIMIT_ENABLED
- Data Source Queue (runtime-toggle) — Controls: Which Celery queue handles queries for this data source. Default: DataSource.queue_name
- Feature Flags (feature-flag) — Controls: Enable/disable features like multi-byte support, dashboard public access. Default: Environment variables
Technology Stack
Frontend UI framework with hooks, context, and component lifecycle for interactive dashboards and query editors
Python web framework providing REST API endpoints, authentication, and request handling
Database ORM for managing queries, users, dashboards, and query results with PostgreSQL backend
Distributed task queue for background query execution, scheduled refreshes, and alert processing
In-memory store for Celery broker, user sessions, and rate limiting counters
Frontend build system that bundles React components, handles hot reloading, and serves development assets
Code editor component providing SQL syntax highlighting, autocomplete, and query editing interface
React UI component library providing forms, tables, modals, and other interface elements
Data visualization library used by chart components to render interactive graphs and plots
Key Components
- QueryExecutor (executor) — Executes queries against data sources, manages timeouts, handles retries, and stores results in cache
redash/tasks/queries.py - QueryRunnerRegistry (registry) — Maps data source types to their specific query runner implementations (PostgreSQL, MySQL, BigQuery, etc)
redash/query_runner/__init__.py - ParameterizedQuery (processor) — Parses mustache-style parameters from query text and substitutes values at execution time
redash/utils/parameterized_query.py - ApplicationArea (orchestrator) — Root React component that handles routing, authentication state, error boundaries, and renders the main app shell
client/app/components/ApplicationArea/index.jsx - QueryEditor (processor) — Ace-based SQL editor with syntax highlighting, autocomplete, schema browser integration, and parameter extraction
client/app/components/queries/QueryEditor/index.js - VisualizationRenderer (transformer) — Takes query results and visualization config to render charts, tables, and other visual representations using D3, Plotly, and custom components
viz-lib/src/visualizations/ - DashboardGrid (orchestrator) — Manages dashboard layout using react-grid-layout, handles widget resizing, positioning, and renders all dashboard widgets
client/app/components/dashboards/DashboardGrid.jsx - AlertEvaluator (validator) — Evaluates alert conditions against query results, triggers notifications when thresholds are met
redash/tasks/alerts.py - CacheManager (store) — Manages query result caching with TTL, handles cache invalidation, and serves cached results to avoid re-execution
redash/models/query_results.py - PermissionService (validator) — Enforces user permissions for queries, dashboards, and data sources based on user roles and object ownership
redash/services/policy.py
Explore the interactive analysis
See the full architecture map, data flow, and code patterns visualization.
Analyze on CodeSeaCompare redash
Related Fullstack Repositories
Frequently Asked Questions
What is redash used for?
Connects to multiple data sources, lets users write SQL queries, creates visualizations and dashboards getredash/redash is a 10-component fullstack written in Python. Data flows through 7 distinct pipeline stages. The codebase contains 860 files.
How is redash architected?
redash is organized into 5 architecture layers: Frontend App, Backend API, Query Execution, Data Layer, and 1 more. Data flows through 7 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.
How does data flow through redash?
Data moves through 7 stages: Query Composition → Parameter Resolution → Query Execution → Result Caching → Visualization Rendering → .... Users write SQL queries in the browser-based editor, which extracts parameters and validates syntax. When executed, queries are sent to the backend where the appropriate query runner connects to the data source, executes the query, and stores results in cache. Results flow to visualization components that render charts and tables, which can be organized into dashboards with filtering and real-time updates. This pipeline design reflects a complex multi-stage processing system.
What technologies does redash use?
The core stack includes React 16.14 (Frontend UI framework with hooks, context, and component lifecycle for interactive dashboards and query editors), Flask (Python web framework providing REST API endpoints, authentication, and request handling), SQLAlchemy (Database ORM for managing queries, users, dashboards, and query results with PostgreSQL backend), Celery (Distributed task queue for background query execution, scheduled refreshes, and alert processing), Redis (In-memory store for Celery broker, user sessions, and rate limiting counters), Webpack (Frontend build system that bundles React components, handles hot reloading, and serves development assets), and 3 more. This broad technology surface reflects a mature project with many integration points.
What system dynamics does redash have?
redash exhibits 4 data pools (Query Results Cache, Redis Session Store), 4 feedback loops, 5 control points, 4 delays. The feedback loops handle recursive and polling. These runtime behaviors shape how the system responds to load, failures, and configuration changes.
What design patterns does redash use?
4 design patterns detected: Query Runner Plugin System, Parameter Templating, Result Caching with Hash Keys, Widget-Dashboard Composition.
How does redash compare to alternatives?
CodeSea has side-by-side architecture comparisons of redash with superset, metabase. These comparisons show tech stack differences, pipeline design, system behavior, and code patterns. See the comparison pages above for detailed analysis.
Analyzed on April 20, 2026 by CodeSea. Written by Karolina Sarna.