Delegated Types in Rails
· One min read
my notes inspired from:
The recordables pattern has been the single-most important architectural pattern we've used on both Basecamp and HEY. It's a key reason both code bases are still a joy to work on. Jeff breaks down the magic in this new podcast. https://t.co/RYB4lMr6Qp
— DHH (@dhh) December 19, 2025
37signals' delegated type pattern - 10+ years of battle-tested architecture
recordings (main table)
id (primary key)
recordable_id (foreign key)
recordable_type (string)
bucket_id (foreign key)
creator_id
parent_id (tree structure)
created_at, updated_at
color, position
✓ Lightweight - no text columns
✓ Billions of rows, small disk size
✓ Never needs migration for new types
✓ Billions of rows, small disk size
✓ Never needs migration for new types
messages (recordable)
id (primary key)
title (text)
content (text)
documents (recordable)
id (primary key)
title (text)
content (text)
format (string)
uploads (recordable)
id (primary key)
filename (string)
file_size (integer)
content_type (string)
storage_key (string)
events (version history)
id (primary key)
recording_id (foreign key)
recordable_id (foreign key)
recordable_type (string)
action (string)
created_at
✓ Tracks all historical versions
✓ Enables "see what changed" feature
✓ Immutable audit trail
✓ Enables "see what changed" feature
✓ Immutable audit trail
Core Principles
- •Recordings are mutable - lightweight pointers that change
- •Recordables are immutable - never modified, only created
- •Events track history - recording → recordable at each moment
- •Tree organization - recordings have parent-child relationships
