ADR-007: Memory Optimization with __slots__¶
Status: ✅ Accepted Date: 2026-01-29 Deciders: Rodrigo Roldán
Context¶
Python objects use __dict__ for attributes, which consumes memory:
__dict__is dynamic, allows adding attributes at runtimeEach instance has overhead of ~240 bytes (Python 3.9+)
For frequently instantiated objects, this adds up
__slots__ is an optimization:
Defines fixed attributes in class
Doesn’t use
__dict__, reduces memory by ~40%Attribute access is faster
Trade-off: cannot add dynamic attributes
Decision¶
Use __slots__ in frequently instantiated classes:
Classes with __slots__:
✅
Response(one per request)✅
Request(one per request)✅
Connection(many in pool)✅
Timeout(one per request)✅
Headers(one per request)
Classes without __slots__:
❌
Session(few instances, mutable by design)❌
ConnectionPool(one per session)❌ Exceptions (rarely instantiated)
Example:
class Response:
__slots__ = (
"raw",
"status_line",
"status_code",
"headers",
"body",
"_text",
"_json",
)
def __init__(self, raw: bytes):
self.raw = raw
self.status_line: str = ""
# ...
Consequences¶
Positive ✅¶
Memory: ~40% less memory per instance
Performance: Faster attribute access
Cache locality: Better CPU cache utilization
Type hints: Attributes declared explicitly
Bugs prevention: Cannot add typos as attributes
Negative ❌¶
Rigidity: Cannot add dynamic attributes
Debugging: Some debuggers assume
__dict__Monkey patching: Not possible (feature, not bug)
Inheritance: Subclasses must declare their own
__slots__
Mitigations¶
Only in stable classes: Don’t use in experimental classes
Document: Indicate that class uses
__slots__Testing: Verify that no attributes are attempted to be added
Memory Savings¶
Estimation (Python 3.9+):
# Without __slots__
Response object: ~280 bytes + data
# With __slots__
Response object: ~170 bytes + data
# For 10,000 requests:
Without __slots__: ~2.8 MB
With __slots__: ~1.7 MB
Savings: ~1.1 MB (39%)
Alternatives Considered¶
Don’t use slots: Rejected. Wastes memory unnecessarily.
Use slots everywhere: Rejected. Makes extensibility difficult.
Use frozen dataclasses: Considered. Less control than slots.