Skip to main content
Memproof includes a PolicyWatcher that monitors your YAML policy file and automatically reloads it when changes are detected. This allows you to update policy rules, risk thresholds, and default behaviors in production without restarting your application.

How It Works

The PolicyWatcher runs a background loop that periodically computes the SHA-256 hash of the policy file. When the hash changes, the watcher parses the new file, validates it, and swaps the active policy configuration. If the new file is invalid, the watcher keeps the previous valid configuration and calls an error callback.

Basic Usage

from memproof.policy.hot_reload import PolicyWatcher

watcher = PolicyWatcher(
    "./memproof.yaml",
    on_reload=lambda cfg: print("Reloaded!"),
)
watcher.start(interval=5.0)

# Your application runs here...

# When shutting down
watcher.stop()

Change Detection

The watcher uses SHA-256 hashing to detect file changes. On each tick it reads the file, computes the hash, and compares it to the last known hash. This approach avoids false reloads caused by file metadata changes (modified timestamps, permissions) that do not affect the file content.
EventBehavior
File content changesNew config is parsed, validated, and swapped in
File unchangedNo action taken
File metadata changes onlyNo action taken (hash is content-based)
File deleted or unreadableError callback fired, previous config retained

Error Handling

Provide an on_error callback to handle cases where the updated policy file is invalid or unreadable. The watcher will continue running and retain the last valid configuration.
from memproof.policy.hot_reload import PolicyWatcher

def handle_reload(cfg):
    print(f"Policy reloaded: {len(cfg.rules)} rules active")

def handle_error(err):
    print(f"Policy reload failed: {err}")
    # Alert your monitoring system, log the error, etc.

watcher = PolicyWatcher(
    "./memproof.yaml",
    on_reload=handle_reload,
    on_error=handle_error,
)
watcher.start(interval=10.0)

Integration with Memproof

To wire the watcher into a running Memproof instance, pass the instance’s reload_policy method as the on_reload callback. This ensures the orchestrator, risk engine, and policy engine all pick up the new configuration atomically.
from memproof import Memproof
from memproof.policy.hot_reload import PolicyWatcher

mp = Memproof(policy="./memproof.yaml", adapter="in_memory")

watcher = PolicyWatcher(
    "./memproof.yaml",
    on_reload=mp.reload_policy,
    on_error=lambda err: print(f"Reload failed: {err}"),
)
watcher.start(interval=5.0)
The policy swap is atomic. In-flight operations that already passed policy evaluation will complete under the old policy. New operations will immediately use the reloaded policy.
Set the polling interval based on your operational needs. Very short intervals (under 1 second) add unnecessary file I/O. For most deployments, 5—10 seconds provides a good balance between responsiveness and overhead.
Combine hot-reload with version-controlled policy files. Push a policy change to your Git repository, have your CI/CD pipeline deploy the updated YAML file, and the PolicyWatcher will pick it up automatically — no rolling restarts required.