Skip to main content

Version control and gradual rollout for application configuration - like git for your config

Project description

Config Time Machine

Version control and gradual rollout for application configuration

Config Time Machine treats configuration like git treats code - every config change is versioned with full history, you can see exactly what settings were live when a bug happened, and you can instantly rollback bad changes.

Features

  • 🕐 Full Version History - Every config change is tracked with timestamp, author, and message
  • Instant Rollbacks - Revert to any previous version with one command
  • 🕵️ Time Travel - Query what config was live at any point in time (great for debugging production issues)
  • 🐦 Canary Deployments - Gradually roll out changes to 10%, then 25%, then 50%, etc.
  • 🧪 A/B Testing - Split traffic between config variants with automatic user assignment
  • ❤️ Health Checks - Automatic rollback when error rates spike
  • Scheduled Rollouts - Deploy config changes at a specific time
  • 🔄 Ring Deployments - Roll out to dev → staging → production
  • Validators - Ensure config values are valid before deployment
  • 📊 Access Logging - Track which config each request used for debugging

Installation

# Core library (no dependencies!)
pip install configtimemachine

# With Redis backend
pip install configtimemachine[redis]

# With SQLite backend (included)
pip install configtimemachine

Quick Start

from configTimeMachine import ConfigTimeMachine

# Create instance
ctm = ConfigTimeMachine()

# Set configuration values (automatically versioned)
ctm.set("database.pool_size", 10, message="Initial pool size")

# Get configuration
pool_size = ctm.get("database.pool_size")  # Returns 10

# Update with history
ctm.set("database.pool_size", 20, message="Increase for traffic spike")

# Oops! Rollback to previous version
ctm.rollback("database.pool_size")  # Back to 10

# See who changed what
for entry in ctm.blame("database.pool_size"):
    print(f"{entry['author']} set {entry['value']} at {entry['timestamp']}")

Gradual Rollouts (Canary Deployments)

Deploy config changes to a percentage of users first:

from configTimeMachine import ConfigTimeMachine, RolloutConfig, RolloutStrategy

ctm = ConfigTimeMachine()

# Roll out new algorithm to 10% of users, then gradually increase
rollout = RolloutConfig(
    strategy=RolloutStrategy.CANARY,
    percentage=10,           # Start at 10%
    target_percentage=100,   # Go to 100%
    increment=10,            # Increase by 10% each step
    increment_interval=300   # Every 5 minutes
)

ctm.set("feature.new_algorithm", True, rollout=rollout)

# Different users get different values based on percentage
ctm.get("feature.new_algorithm", user_id="user_123")  # Might be True or False

A/B Testing

Split traffic between variants:

ctm.set_ab_test(
    "button.color",
    variants={
        "control": ("#3498db", 50),    # Blue for 50%
        "treatment": ("#e74c3c", 50),  # Red for 50%
    }
)

# Users consistently get the same variant
color = ctm.get("button.color", user_id="user_456")

# Check which variant a user has
variant = ctm.get_user_variant("button.color", "user_456")

Time Travel Debugging

See what config was live when a bug happened:

from datetime import datetime, timezone

# What was the pool_size at 3:47 AM when we had that outage?
outage_time = datetime(2024, 1, 15, 3, 47, tzinfo=timezone.utc)
pool_size = ctm.get_at_time("database.pool_size", outage_time)

# Get a complete snapshot of all configs at that time
snapshot = ctm.what_was_live(outage_time)

Validators

Ensure config values are valid:

from configTimeMachine import RangeValidator, TypeValidator, EnumValidator

# Only allow integers between 1 and 100
ctm.add_validator("pool_size", TypeValidator(int))
ctm.add_validator("pool_size", RangeValidator(min_value=1, max_value=100))

# Only allow specific values
ctm.add_validator("log_level", EnumValidator(["DEBUG", "INFO", "WARNING", "ERROR"]))

# This will raise ValueError
ctm.set("pool_size", 9999)  # ValueError: Value must be <= 100

Health Checks with Auto-Rollback

Automatically rollback when things go wrong:

from configTimeMachine import ErrorRateHealthCheck

def get_error_rate():
    # Return current error rate from your monitoring
    return 0.05  # 5%

ctm.add_health_check(
    "database.pool_size",
    ErrorRateHealthCheck(get_error_rate, threshold=0.1)
)

# During gradual rollout, if error rate exceeds 10%, 
# the config automatically rolls back

Storage Backends

In-Memory (Default)

ctm = ConfigTimeMachine()  # Uses InMemoryStorage

File Storage

from configTimeMachine import FileStorage

ctm = ConfigTimeMachine(storage=FileStorage("/path/to/config"))

SQLite (Persistent)

from configTimeMachine.sqlite_storage import SQLiteStorage

ctm = ConfigTimeMachine(storage=SQLiteStorage("config.db"))

Redis (Production)

from configTimeMachine.redis_storage import RedisStorage

ctm = ConfigTimeMachine(storage=RedisStorage(
    host="localhost",
    port=6379,
    password="your_password"
))

Event Callbacks

React to config changes:

def on_pool_size_change(key, value, version):
    print(f"Pool size changed to {value} by {version.author}")
    # Reconfigure connection pool...

ctm.on_change("database.pool_size", on_pool_size_change)

Watch for Changes

Block until a config changes:

# Wait for config to change (useful for background workers)
new_value = ctm.watch("feature.enabled", timeout=30)

Scheduled Deployments

Deploy config at a specific time:

from datetime import datetime, timezone, timedelta

# Deploy maintenance mode in 1 hour
deploy_time = datetime.now(timezone.utc) + timedelta(hours=1)

ctm.set(
    "maintenance_mode",
    True,
    rollout=RolloutConfig(
        strategy=RolloutStrategy.SCHEDULED,
        scheduled_time=deploy_time
    )
)

Ring-Based Deployments

Roll out through environments:

# For a staging instance
ctm = ConfigTimeMachine(environment="staging")

# This will only deploy when environment matches "production"
ctm.set(
    "new_feature",
    True,
    rollout=RolloutConfig(
        strategy=RolloutStrategy.RING,
        ring="production"
    )
)

API Reference

ConfigTimeMachine

Method Description
set(key, value, ...) Set a config value with versioning
get(key, default, ...) Get a config value
delete(key) Delete a config (creates tombstone)
history(key, limit) Get version history
rollback(key, ...) Rollback to previous version
get_at_time(key, timestamp) Time travel query
diff(key, v1, v2) Compare two versions
blame(key) Git-blame style history
snapshot() Get all current config values
set_ab_test(...) Set up A/B test
add_validator(...) Add config validator
add_health_check(...) Add health check
on_change(...) Register change callback
watch(key, timeout) Wait for config change
stop() Stop background threads

Why Config Time Machine?

Feature Plain Config Files Feature Flags Service Config Time Machine
Version history
Instant rollback
Time travel queries
Gradual rollouts
A/B testing
Health-based rollback
No external service
Self-hosted
No dependencies

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

configtimemachine-0.1.0.tar.gz (24.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

configtimemachine-0.1.0-py3-none-any.whl (21.6 kB view details)

Uploaded Python 3

File details

Details for the file configtimemachine-0.1.0.tar.gz.

File metadata

  • Download URL: configtimemachine-0.1.0.tar.gz
  • Upload date:
  • Size: 24.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for configtimemachine-0.1.0.tar.gz
Algorithm Hash digest
SHA256 dbdc9d86d761f280e707195bc4fc13d31b6bd1df307b12dc5b1b89bb429ed1a4
MD5 9fc547944d9c4702696a4c1ae756eb49
BLAKE2b-256 7efcb2ebb02889485695c83571a73c8fa372bd33e645f4a3b78d31a8cabb889a

See more details on using hashes here.

File details

Details for the file configtimemachine-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for configtimemachine-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 92e9e8033aced3a35f6233f4f6cc353558828fee539f5b44187a8ad0797a67bd
MD5 ac342e4359cff893915f62a69ae9cbf3
BLAKE2b-256 27c64566c1d84d3060469174c6328be67013e6037c97f16e3b3860a6fadf012b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page