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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dbdc9d86d761f280e707195bc4fc13d31b6bd1df307b12dc5b1b89bb429ed1a4
|
|
| MD5 |
9fc547944d9c4702696a4c1ae756eb49
|
|
| BLAKE2b-256 |
7efcb2ebb02889485695c83571a73c8fa372bd33e645f4a3b78d31a8cabb889a
|
File details
Details for the file configtimemachine-0.1.0-py3-none-any.whl.
File metadata
- Download URL: configtimemachine-0.1.0-py3-none-any.whl
- Upload date:
- Size: 21.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
92e9e8033aced3a35f6233f4f6cc353558828fee539f5b44187a8ad0797a67bd
|
|
| MD5 |
ac342e4359cff893915f62a69ae9cbf3
|
|
| BLAKE2b-256 |
27c64566c1d84d3060469174c6328be67013e6037c97f16e3b3860a6fadf012b
|