growthbook/growthbook

Open Source Feature Flags, Experimentation, and Product Analytics

7,672 stars TypeScript 7 components

13 hidden assumptions · 6-stage pipeline · 7 components

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

Routes experiments between users based on feature flags and analyzes statistical results

Feature definitions flow from backend MongoDB storage through API endpoints to client SDKs, which evaluate experiments locally and send tracking data back. Statistical analysis runs on aggregated experiment data in connected data warehouses, with results flowing back through the API to update bandit weights and display results in the web dashboard.

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

A 7-component fullstack. 2153 files analyzed. Data flows through 6 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

License server API calls fail with authentication errors, breaking billing operations and payment updates, with no clear error handling for invalid credentials

Worth your attention first

Large seed values cause numpy.random.seed() to fail with ValueError, crashing bandit weight calculations and breaking experiment traffic allocation

Worth your attention first

When thousands of SDK instances refresh at once, backend API gets overwhelmed, causing 503 errors and stale feature flags serving to users

Show everything (10 more)
Contract

SDK feature requests contain project context in headers or query params, but router assumes this data is always present and valid

If this fails: Missing or invalid project context causes features to be served from wrong organization or default to empty feature set, leading to incorrect experiment assignments

packages/back-end/src/api/api.router.ts:feature endpoints
Resource

External data warehouse connections (BigQuery, Snowflake) have unlimited query capacity and always return results within Express request timeout

If this fails: Long-running metric aggregation queries time out or hit rate limits, causing statistical analysis to fail with incomplete data and blocking experiment result updates

packages/back-end/src/controllers/datasources.ts:data warehouse queries
Scale

min_variation_weight of 0.01 (1%) assumes experiments never need traffic allocation below this threshold, hardcoded in BanditConfig

If this fails: Experiments with many variations (>100) cannot allocate minimum viable traffic to each arm, causing statistical power issues and invalid bandit optimization

packages/stats/gbstats/bayesian/bandits.py:min_variation_weight
Ordering

useExperiments hook returns experiments in consistent order for pagination, but assumes experiments array doesn't change between page renders

If this fails: User sees duplicate experiments or missing experiments when navigating pages if new experiments are added during browsing session

packages/front-end/pages/bandits/index.tsx:experiment filtering
Environment

Express trust proxy configuration assumes specific load balancer setup (AWS ALB, CloudFlare, etc.) without validating the proxy chain

If this fails: Incorrect client IP detection in production leads to wrong user attribution in experiments and security issues with rate limiting bypasses

packages/back-end/src/app.ts:EXPRESS_TRUST_PROXY_OPTS
Shape

Hardcoded cursor positions array assumes fixed UI dimensions and screen resolution, with exact pixel coordinates for interactive elements

If this fails: Animated cursors render in wrong positions on different screen sizes or when UI layout changes, breaking the managed warehouse onboarding flow

packages/front-end/pages/datasources/index.tsx:ManagedWarehouse cursors
Contract

TrackingCallback functions are synchronous or handle errors internally, but SDK assumes they never throw exceptions

If this fails: User-provided tracking callbacks that throw errors crash the SDK experiment evaluation, causing features to fallback to default values

packages/sdk-js/src/index.ts:TrackingCallback
Temporal

UNLIMITED_USAGE.lastUpdated timestamp assumes current system time represents accurate billing period boundaries

If this fails: Server clock skew or timezone issues cause billing period calculations to be wrong, potentially allowing usage overages or incorrect quota enforcement

packages/back-end/src/enterprise/billing/index.ts:UNLIMITED_USAGE
Domain

Demo datasource exports assume specific data schema matches production warehouse table structures exactly

If this fails: Users testing with demo data get different statistical results than production, leading to incorrect experiment setup and misleading A/B test outcomes

packages/shared/src/demo-datasource/index.ts:demo data format
Resource

Design system page loads all component stories simultaneously, assuming browser can handle rendering dozens of complex React components at once

If this fails: Design system page becomes unresponsive on lower-end devices or with limited memory, making it impossible to preview UI components during development

packages/front-end/pages/design-system/index.tsx:component stories

Open the standalone hidden-assumptions report for growthbook →

How Data Flows Through the System

Feature definitions flow from backend MongoDB storage through API endpoints to client SDKs, which evaluate experiments locally and send tracking data back. Statistical analysis runs on aggregated experiment data in connected data warehouses, with results flowing back through the API to update bandit weights and display results in the web dashboard.

  1. Feature definition serving — Backend API serves feature definitions with embedded experiment rules from MongoDB to requesting SDKs via GET /api/features endpoint, including targeting conditions and variation configurations (config: datasources.warehouse.params, metrics.signups.type)
  2. Client-side feature evaluation — GrowthBook SDK evaluates feature flags and experiments by checking user attributes against targeting rules, assigning users to variations based on hash bucketing, and determining feature values [FeatureDefinition → FeatureResult]
  3. Experiment tracking — SDK calls trackingCallback with experiment exposure data including user ID, experiment details, and assigned variation, typically sent to analytics platforms or backend tracking endpoints [FeatureResult → TrackingData]
  4. Metric data aggregation — Backend queries connected data warehouses using DataSourceManager to aggregate user metrics, conversion rates, and experiment exposure data for statistical analysis input [TrackingData → Experiment statistics] (config: datasources.warehouse.settings.queries.exposure, datasources.warehouse.params.host)
  5. Statistical analysis — Python stats package runs Bayesian or frequentist tests on experiment data using methods like CUPED variance reduction and sequential testing to compute significance and confidence intervals [Experiment statistics → BanditResult] (config: bandit_weights_seed, top_two, min_variation_weight)
  6. Results presentation — Frontend retrieves statistical results via API and renders experiment dashboards showing conversion rates, significance levels, bandit weight updates, and traffic allocation recommendations [BanditResult]

Data Models

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

FeatureDefinition packages/shared/types/feature.ts
object with id: string, key: string, rules: FeatureRule[], defaultValue: JSONValue, version: number, environments: Record<string, FeatureEnvironment>
Created in backend API, cached and served to SDKs, evaluated locally by clients based on user attributes
ExperimentInterface packages/shared/types/experiment.ts
object with id: string, name: string, hypothesis: string, variations: Variation[], targeting: ExperimentTargetingData, status: ExperimentStatus, metrics: string[], phases: ExperimentPhase[]
Defined in web UI, stored in MongoDB, embedded in feature rules, generates statistical results through Python analytics engine
BanditResult packages/stats/gbstats/models/results.py
dataclass with singleVariationResults: List[SingleVariationResult], currentWeights: List[float], updatedWeights: List[float], bestArmProbabilities: List[float], seed: int, updateMessage: str
Generated by Python bandit algorithms using experiment data, returned via API to frontend for display in bandit dashboards
TrackingData packages/sdk-js/src/types/growthbook.ts
object with experiment: Experiment, result: Result, user: UserContext with userId, attributes, experimentBucket, variationId, variationName
Created when SDK evaluates experiments, sent to tracking callbacks, aggregated for statistical analysis of experiment results

System Behavior

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

Data Pools

Feature definitions cache (cache)
Client-side cache storing feature definitions with TTL expiration and background refresh
MongoDB experiments (database)
Primary persistence layer storing organization data, experiments, feature flags, and user assignments
Data warehouse metrics (database)
External analytics databases (BigQuery, Snowflake) containing user behavior and conversion metrics for statistical analysis
Bandit weights cache (in-memory)
Runtime storage for current traffic allocation weights updated by bandit algorithms

Feedback Loops

Delays

Control Points

Technology Stack

Express.js (framework)
HTTP server framework powering the backend API with middleware for authentication, routing, and request processing
Next.js (framework)
React framework providing the web dashboard with server-side rendering and file-based routing
MongoDB (database)
Primary database storing organizations, experiments, feature flags, and user data with Mongoose ODM
Python (runtime)
Statistical computation engine implementing Bayesian and frequentist analysis methods with NumPy and SciPy
TypeScript (runtime)
Primary language providing type safety across backend API, frontend, and SDK packages
Docker (infra)
Containerization for self-hosted deployments with docker-compose orchestration
PM2 (infra)
Process manager for production deployments with clustering and monitoring capabilities
PNPM (build)
Package manager with workspace support for managing dependencies across the monorepo packages

Key Components

Package Structure

back-end (app)
Express.js API server that manages organizations, experiments, feature flags, and statistical analyses, connecting to MongoDB for persistence and integrating with various data warehouses.
front-end (app)
Next.js web application providing the GrowthBook dashboard UI for managing experiments, feature flags, and viewing analytics results.
growthbook (library)
JavaScript SDK that fetches feature definitions from the backend API and evaluates feature flags and experiments client-side based on user attributes.
growthbook-react (library)
React wrapper around the JavaScript SDK providing hooks and components for feature flag evaluation in React applications.
shared (shared)
Common TypeScript types and utilities shared between backend and frontend packages.
stats (library)
Python package implementing Bayesian and frequentist statistical methods for analyzing A/B test results, including bandit algorithms and CUPED variance reduction.

Explore the interactive analysis

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

Analyze on CodeSea

Related Fullstack Repositories

Frequently Asked Questions

What is growthbook used for?

Routes experiments between users based on feature flags and analyzes statistical results growthbook/growthbook is a 7-component fullstack written in TypeScript. Data flows through 6 distinct pipeline stages. The codebase contains 2153 files.

How is growthbook architected?

growthbook is organized into 4 architecture layers: Client SDKs, Web Dashboard, API Backend, Statistical Engine. Data flows through 6 distinct pipeline stages. This layered structure keeps concerns separated and modules independent.

How does data flow through growthbook?

Data moves through 6 stages: Feature definition serving → Client-side feature evaluation → Experiment tracking → Metric data aggregation → Statistical analysis → .... Feature definitions flow from backend MongoDB storage through API endpoints to client SDKs, which evaluate experiments locally and send tracking data back. Statistical analysis runs on aggregated experiment data in connected data warehouses, with results flowing back through the API to update bandit weights and display results in the web dashboard. This pipeline design reflects a complex multi-stage processing system.

What technologies does growthbook use?

The core stack includes Express.js (HTTP server framework powering the backend API with middleware for authentication, routing, and request processing), Next.js (React framework providing the web dashboard with server-side rendering and file-based routing), MongoDB (Primary database storing organizations, experiments, feature flags, and user data with Mongoose ODM), Python (Statistical computation engine implementing Bayesian and frequentist analysis methods with NumPy and SciPy), TypeScript (Primary language providing type safety across backend API, frontend, and SDK packages), Docker (Containerization for self-hosted deployments with docker-compose orchestration), and 2 more. A focused set of dependencies that keeps the build manageable.

What system dynamics does growthbook have?

growthbook exhibits 4 data pools (Feature definitions cache, MongoDB experiments), 3 feedback loops, 4 control points, 3 delays. The feedback loops handle training-loop and polling. These runtime behaviors shape how the system responds to load, failures, and configuration changes.

What design patterns does growthbook use?

4 design patterns detected: Feature Flag Evaluation, Multi-Armed Bandit, Warehouse-Native Analytics, SDK-First Architecture.

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