Writing Secrets

Programmatically add or update secrets from your application.

The set() method allows your application to add or update secrets programmatically, enabling dynamic configuration, feature flags, and more.

Basic Usage#

await redenv.set("LOG_LEVEL", "debug")
redenv.set("LOG_LEVEL", "debug")

This encrypts and writes the new value to Redis, creating a new version entry.

How It Works#

When you call set():

  1. Encrypts the value locally using the Project Encryption Key (PEK)
  2. Writes the encrypted value to Redis as a new version
  3. Clears the local cache to ensure fresh data on next read

Practical Examples#

Feature Flags#

Toggle features in real-time without redeploying:

routes/admin.py
from fastapi import APIRouter
from config.redenv import redenv

router = APIRouter()

@router.post("/admin/feature/{name}")
async def toggle_feature(name: str, enabled: bool):
    await redenv.set(f"FEATURE_{name.upper()}", str(enabled))
    return {"success": True, "feature": name, "enabled": enabled}
routes/admin.py
from flask import Blueprint, request
from config.redenv import redenv

admin = Blueprint("admin", __name__)

@admin.route("/admin/feature/<name>", methods=["POST"])
def toggle_feature(name):
    enabled = request.json.get("enabled")
    redenv.set(f"FEATURE_{name.upper()}", str(enabled))
    return {"success": True, "feature": name, "enabled": enabled}
Check the feature flag elsewhere
secrets = redenv.load()
beta_enabled = secrets.get("FEATURE_BETA", False, cast=bool)

if beta_enabled:
    # Show beta features
    pass

Dynamic Log Levels#

Adjust logging without restart:

# Increase verbosity during an incident
await redenv.set("LOG_LEVEL", "debug")

# Return to normal after investigation
await redenv.set("LOG_LEVEL", "info")
# Increase verbosity during an incident
redenv.set("LOG_LEVEL", "debug")

# Return to normal after investigation
redenv.set("LOG_LEVEL", "info")

Rate Limit Adjustments#

Respond to traffic changes:

# During high traffic, increase limits
await redenv.set("RATE_LIMIT_REQUESTS", "1000")
await redenv.set("RATE_LIMIT_WINDOW", "60")

# Normal operations
await redenv.set("RATE_LIMIT_REQUESTS", "100")
# During high traffic, increase limits
redenv.set("RATE_LIMIT_REQUESTS", "1000")
redenv.set("RATE_LIMIT_WINDOW", "60")

# Normal operations
redenv.set("RATE_LIMIT_REQUESTS", "100")

Maintenance Mode#

async def enable_maintenance_mode(reason: str):
    await redenv.set("MAINTENANCE_MODE", "true")
    await redenv.set("MAINTENANCE_REASON", reason)

async def disable_maintenance_mode():
    await redenv.set("MAINTENANCE_MODE", "false")
def enable_maintenance_mode(reason: str):
    redenv.set("MAINTENANCE_MODE", "true")
    redenv.set("MAINTENANCE_REASON", reason)

def disable_maintenance_mode():
    redenv.set("MAINTENANCE_MODE", "false")

Auditing#

All writes are audited. The token_id is recorded with each version:

# Your write operation
redenv.set("API_KEY", "new-value")

# In the version history (viewable via CLI):
# Version 5: { value: "...", tokenId: "stk_...", timestamp: "..." }

Use redenv history view API_KEY to see who changed what and when.

Error Handling#

from redenv import RedenvError

try:
    redenv.set("KEY", "value")
    print("Secret updated successfully")
except RedenvError as e:
    print("Failed to write secret:", e.message)
    raise

Cache Behavior#

After a set() call, the local cache is cleared:

# Load current secrets
secrets = await redenv.load()
print(secrets["MY_KEY"])  # "old-value"

# Update the secret
await redenv.set("MY_KEY", "new-value")

# Next load gets fresh data
secrets = await redenv.load()
print(secrets["MY_KEY"])  # "new-value"
# Load current secrets
secrets = redenv.load()
print(secrets["MY_KEY"])  # "old-value"

# Update the secret
redenv.set("MY_KEY", "new-value")

# Next load gets fresh data
secrets = redenv.load()
print(secrets["MY_KEY"])  # "new-value"

Best Practices#

  1. Audit writes - Regularly review version history for unexpected changes
  2. Validate inputs - Sanitize values before writing
def update_log_level(level: str):
    valid_levels = ["debug", "info", "warn", "error"]

    if level not in valid_levels:
        raise ValueError(f"Invalid log level: {level}")

    redenv.set("LOG_LEVEL", level)

Limitations#

  • String values only - Convert objects to JSON strings
  • No bulk writes - Call set() for each key
  • Version history - Each write creates a new version
import json

# Writing JSON
redenv.set("CONFIG", json.dumps({
    "feature": "enabled",
    "timeout": 5000,
}))

# Reading it back
config = secrets.get("CONFIG", cast=dict)