How ChaosBlade Uses SQLite to Track Experiment State: Internal Database Mechanisms

ChaosBlade persists every chaos experiment in a local SQLite file (chaosblade.dat) using the glebarez/sqlite driver, tracking lifecycle states through a singleton data.Source interface that manages the experiment table with columns for UID, status, error messages, and timestamps.

The chaosblade-io/chaosblade project implements a lightweight persistence layer to track the complete lifecycle of chaos engineering experiments. By leveraging a local SQLite database, the tool maintains a single source of truth for experiment state without requiring external database dependencies. This article examines how the SQLite database tracks experiment state through the data package, revealing the schema design, state transition logic, and CRUD operations that power ChaosBlade's experiment management.

SQLite Database Architecture in ChaosBlade

Database File Location and Configuration

The SQLite database file path is resolved by the GetDataFilePath() function in data/source.go. By default, the system creates a file named chaosblade.dat in the working directory. Administrators can override this location by setting the CHAOSBLADE_DATAFILE_PATH environment variable before starting the ChaosBlade CLI or server.

The Data Source Singleton Pattern

ChaosBlade opens the database through the standard database/sql package using the glebarez/sqlite driver. The GetSource() function implements a singleton pattern, ensuring that all components share a single data.Source instance. This singleton manages the database connection and provides thread-safe access to the experiment table across the application.

How the Experiment Table Tracks State

Table Schema and Initialization

The experiment table is created automatically on first run via CheckAndInitExperimentTable() in data/experiment.go. The initialization logic executes CREATE TABLE IF NOT EXISTS experiment with columns for uid, command, sub_command, flag, status, error, create_time, and update_time. This schema stores a single row per experiment, capturing the complete configuration and current state.

Status Column and Lifecycle Values

The status column implements the state machine for experiment lifecycle management. Valid values include Created, Running, Success, Error, and Destroyed. State transitions occur through the UpdateExperimentModelByUid() function, which atomically updates both the status and the update_time timestamp. This ensures that concurrent operations maintain consistency in the SQLite database track experiment state.

Error Handling and Audit Trails

When experiments fail, the error column stores the error message string alongside the status update. The create_time and update_time columns use RFC-3339 Nano format timestamps, providing a chronological audit trail for every state change. This design enables post-mortem analysis by preserving the exact sequence of events and any error messages generated during execution.

Code Examples: Working with Experiment State

Initializing the Database and Table

src := data.GetSource()               // singleton creation
src.CheckAndInitExperimentTable()    // auto-creates table if absent

Relevant source: data/source.go lines 50-59.

Creating a New Experiment Record

model := &data.ExperimentModel{
    Uid:        uid,
    Command:    cmd,
    SubCommand: sub,
    Flag:       flag,
    Status:     "Created",
    CreateTime: time.Now().Format(time.RFC3339Nano),
    UpdateTime: time.Now().Format(time.RFC3339Nano),
}
src.InsertExperimentModel(model)

Relevant source: InsertExperimentModel in data/experiment.go lines 42-48.

Updating Status During Execution

src.UpdateExperimentModelByUid(uid, "Running", "")
// … after execution
src.UpdateExperimentModelByUid(uid, "Success", "")
// or on error
src.UpdateExperimentModelByUid(uid, "Error", errMsg)

Relevant source: UpdateExperimentModelByUid in data/experiment.go lines 64-68.

Querying Experiment State

exp, _ := src.QueryExperimentModelByUid(uid)
fmt.Printf("UID %s – status: %s, error: %s\n", exp.Uid, exp.Status, exp.Error)

Relevant source: QueryExperimentModelByUid in data/experiment.go lines 80-98.

Deleting Completed Experiments

src.DeleteExperimentModelByUid(uid)

Relevant source: DeleteExperimentModelByUid in data/experiment.go lines 4-11.

State Transitions During the Experiment Lifecycle

The SQLite database track experiment state through a well-defined lifecycle managed by the exec package executors. The flow follows these stages:

  1. Bootstrap – The first call to GetSource() creates the singleton Source instance and opens the SQLite file using sql.Open("sqlite", GetDataFilePath()).

  2. Table InitializationCheckAndInitExperimentTable() verifies existence via ExperimentTableExists(); if missing, InitExperimentTable() executes the DDL to create the experiment table.

  3. Creation – When users run blade create, the system calls InsertExperimentModel to persist a row with status Created, capturing the command, flags, and timestamps.

  4. Execution – Executors in exec/*/executor.go invoke UpdateExperimentModelByUid(uid, "Running", "") before injecting faults. Upon completion, they update to Success or Error with the error message.

  5. Query – The blade status command uses QueryExperimentModelByUid or QueryExperimentModels to retrieve current state from the SQLite database track experiment state storage.

  6. Destruction – After blade destroy completes successfully, the status updates to Destroyed and DeleteExperimentModelByUid may remove the row entirely.

This design ensures that the SQLite database track experiment state remains consistent even if the ChaosBlade process restarts, providing durable persistence for chaos engineering operations.

Summary

  • ChaosBlade stores all experiment data in a local SQLite file (chaosblade.dat) managed through the data.Source singleton.
  • The experiment table schema includes columns for UID, command configuration, status, error messages, and RFC-3339 Nano timestamps.
  • State transitions (Created → Running → Success/Error/Destroyed) occur through UpdateExperimentModelByUid in data/experiment.go.
  • The SQLite database track experiment state without external dependencies, enabling both CLI and server modes to share persistent storage.
  • All CRUD operations are thread-safe through the singleton pattern, ensuring consistency across concurrent chaos experiments.

Frequently Asked Questions

Where is the ChaosBlade SQLite database file located?

By default, ChaosBlade creates the chaosblade.dat file in the current working directory. You can override this location by setting the CHAOSBLADE_DATAFILE_PATH environment variable before starting the ChaosBlade CLI or server process. The path resolution logic is implemented in the GetDataFilePath() function within data/source.go.

What are the possible experiment statuses in the SQLite database?

The status column in the experiment table supports five lifecycle values: Created (initial state), Running (active execution), Success (completed without errors), Error (execution failed with error message stored), and Destroyed (cleaned up). These states are managed through the UpdateExperimentModelByUid function in data/experiment.go.

How does ChaosBlade ensure thread-safe access to the SQLite database?

ChaosBlade implements a singleton pattern through the GetSource() function in data/source.go, which returns a single data.Source instance shared across the application. This singleton manages the sql.DB connection pool returned by sql.Open("sqlite", ...), ensuring that all concurrent experiment operations access the SQLite database through a single coordinated entry point.

Can I query the ChaosBlade experiment state directly via SQL?

Yes, since ChaosBlade uses a standard SQLite file, you can query the experiment table directly using the sqlite3 command-line tool or any SQLite client. The table schema includes uid, command, sub_command, flag, status, error, create_time, and update_time columns. However, direct modifications are not recommended as they may interfere with ChaosBlade's internal state management logic.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →