December 16th, 2025
The Day We Redesigned the Schema Today was a case study in schema design. We started with a naive approach, hit real problems, and arrived at a metric-based architecture that actually scales. This is the complete journey.The Problem Context
Q: What were we trying to build? A task/commitment system where users can create tasks with different verification conditions:- Time (within / outside a time window)
- Location (within a radius)
- App usage restrictions
- AI-based activity verification
- Photo / video proof
- Accountability partner approval
The Initial (Naive) Schema
Q: What was our first approach? Store conditions as attributes directly:- Very readable
- Easy to understand
- Direct mapping from UI to backend
- Felt “clean” and straightforward
Problems with the Initial Design
Problem 1 — Schema Locks Feature Growth
Every new condition requires:- Adding a new key in conditions
- Updating backend logic
- Updating validation
- Handling old tasks without the new field
Problem 2 — Backend Must Guess the Rule
Example:- Is this “never open”?
- Is it “open less than X times”?
- Is it “only blocked during task time”?
Problem 3 — Backend Logic Grows Uncontrollably
Backend ends up with logic like:- Adds a new if
- Increases coupling
- Makes backend harder to maintain
The Key Insight (Turning Point)
Q: What was the core realization? This is where my friend Atheeq stepped in. My first approach was bad and naive. I was storing only values and attributes, and expecting the backend to decide the rule. Atheeq suggested the metric-based approach, and at first I didn’t fully get why it was better. But after working through the problems above, I now clearly understand why his approach was better: A good schema must also encode the rule intent. Backend should execute declared rules, not infer rules. Thanks Atheeq 👊The Metric-Based Schema Design
Q: What’s the new approach? We redesigned conditions into a generic rule structure:- Fixed
- Generic
- Data-driven
- Future-proof
Why a Separate Metrics Definition Exists
Q: What is the metrics registry for? To support and validate conditions, we added a global metric registry:- Defines what a metric is
- Restricts allowed relations
- Restricts target types
- Declares permissions required
metrics→ what is possibleconditions→ what is required
Concrete Example — Location Condition
Stored condition:How Backend Evaluates This
Step 1 — Fetch current user locationWhy This Is Scalable
Q: Does this actually remove if/else? No — but here’s the important realization: Yes, if/else still exists — but:- The number of if/else blocks is fixed per metric
- It does not grow per task
- It does not grow per condition
The Final Learning
Q: What are the key lessons learned?- Schemas should encode rule intent, not just data
- Backend should execute rules, not infer them
- Hard-coding happens when logic depends on schema shape
- Good abstractions freeze where complexity lives
- Scalability comes from bounded logic, not fewer lines
One-Line Takeaway
We don’t remove if/else. We control where they live — and keep them from spreading.Summary
Today was about schema architecture. We went from:- My naive attribute-based conditions
- To understanding why that doesn’t scale
- To Atheeq’s metric-based architecture with explicit rules