Dimensional Safety for Configuration¶
Configuration files often contain values with implicit units. This guide shows how to make units explicit and catch dimension errors at load time.
The Problem¶
Consider a typical configuration:
timeout: 30 # seconds? milliseconds?
threshold: 99.9 # percent? ratio?
distance: 100 # meters? kilometers? miles?
Implicit units create bugs when:
- Someone assumes
timeout: 30means seconds, but it's milliseconds - A threshold is treated as a percentage when it's a raw ratio
- Units change between environments (metric vs imperial)
The Solution: Explicit Units¶
Use Pydantic models with Number fields:
from pydantic import BaseModel
from ucon import Dimension
from ucon.pydantic import Number
class ServiceConfig(BaseModel):
timeout: Number[Dimension.time]
retry_interval: Number[Dimension.time]
max_distance: Number[Dimension.length]
Now configuration must include units:
timeout:
quantity: 30
unit: s
retry_interval:
quantity: 500
unit: ms
max_distance:
quantity: 100
unit: km
Loading Configuration¶
import yaml
with open("config.yaml") as f:
data = yaml.safe_load(f)
config = ServiceConfig(**data)
print(config.timeout) # <30 s>
Dimension mismatches fail at load time:
SRE Example: Availability Thresholds¶
SRE configurations often involve availability ("nines"), percentages, and time windows:
from pydantic import BaseModel
from ucon import Dimension
from ucon.pydantic import Number
class SLOConfig(BaseModel):
target_availability: Number[Dimension.ratio]
error_budget_window: Number[Dimension.time]
alert_threshold: Number[Dimension.ratio]
target_availability:
quantity: 99.99
unit: percent
error_budget_window:
quantity: 30
unit: day
alert_threshold:
quantity: 4
unit: nines
Convert between representations at runtime:
from ucon import units
# Convert nines to percentage
threshold_pct = config.alert_threshold.to(units.percent)
print(threshold_pct) # <99.99 %>
# Convert percentage to nines
target_nines = config.target_availability.to(units.nines)
print(target_nines) # <4.0 nines>
Error Messages¶
When dimensions mismatch, you get clear error messages:
# If someone puts a length where time is expected:
config = ServiceConfig(
timeout={"quantity": 30, "unit": "km"}, # Wrong!
...
)
# ValidationError: timeout: expected dimension 'time', got 'length'
Best Practices¶
- Always use dimensional constraints for physical quantities
- Document expected units in config comments, but enforce via types
- Use the most natural unit for the domain (seconds for timeouts, nines for SLOs)
- Convert at the boundary - convert to internal units after loading