Skip to content

Roadmapping

Modality's roadmapping feature helps you plan data platform development by automatically scheduling tasks based on dependencies, team capacity, and estimated effort.

Overview

Roadmapping in Modality provides:

  1. Automatic task generation from your data model
  2. Intelligent dependency suggestions based on entity relationships
  3. Capacity-based scheduling using team size and availability
  4. Visual timeline with Gantt chart representation
  5. Progress tracking with task statuses
  6. Manual overrides for custom scenarios

Core Concepts

Tasks

A task represents work to be done:

  • Entity tasks: Build a data entity (table, view, model)
  • Source tasks: Integrate a data source
  • Report tasks: Build a dashboard or report
  • Component tasks: Create cube, metric, API, stream, or reverse-ETL
  • Data product tasks: Package a complete data product

Each task includes:

  • Estimated hours: From estimation model or defaults
  • Dependencies: Other tasks that must complete first
  • Assignment: Who's working on it
  • Status: not-started, in-progress, completed
  • Dates: Calculated start and end dates

Dependencies

Tasks can depend on other tasks, creating a critical path:

Automatic dependencies are suggested based on:

  • Entity relationships (belongs-to, derived-from, contains)
  • Entities used in reports and metrics
  • Logical model mappings

Manual dependencies can be added or overridden.

Team Capacity

Schedule calculated based on:

  • Team size: Number of people available
  • Hours per day: Available hours per person per day
days_required = CEIL(estimated_hours / (team_size * hours_per_day))

Roadmap Configuration

Basic Setup

mml
roadmap {
  start_date = "2025-01-01"
  team_size = 2
  hours_per_day = 6
}

Attributes

  • start_date: When the project begins (ISO date format)
  • team_size: Number of people on the team (default: 2)
  • hours_per_day: Available hours per person per day (default: 6)

Example configurations:

mml
# Solo developer
roadmap {
  start_date = "2025-01-15"
  team_size = 1
  hours_per_day = 8
}

# Small team, part-time
roadmap {
  start_date = "2025-02-01"
  team_size = 3
  hours_per_day = 4
}

# Full team, dedicated
roadmap {
  start_date = "2025-03-01"
  team_size = 5
  hours_per_day = 8
}

Task Types

Entity Tasks

Tasks for building data entities.

mml
task "Build Customer Entity" {
  builds "Sales.Customer"
  depends_on "Integrate CRM Source"
  assignee = "alice"
  status = "in-progress"
}

Attributes:

  • builds: Reference to entity ("Domain.Entity")
  • depends_on: Task dependencies (optional, auto-suggested)
  • assignee: Person responsible (optional)
  • status: "not-started" | "in-progress" | "completed" (default: "not-started")
  • manual_hours: Override estimated hours (optional)
  • notes: Task notes (optional)

Hour estimation: Pulled from entity_estimate or default (8 hours)

Auto-suggested dependencies:

  • Entities referenced in belongs-to
  • Entities referenced in derived-from
  • Entities referenced in contains

Source Tasks

Tasks for integrating data sources.

mml
task "Integrate Production Database" {
  builds "PostgreSQL_Production"
  assignee = "bob"
  status = "completed"
}

Attributes:

  • builds: Reference to source ("SourceName")
  • depends_on: Task dependencies (optional)
  • assignee: Person responsible (optional)
  • status: Task status (default: "not-started")
  • manual_hours: Override estimated hours (optional)
  • notes: Task notes (optional)

Hour estimation: Pulled from source_estimate or default (8 hours)

Auto-suggested dependencies: None (sources are typically first tasks)

Report Tasks

Tasks for building dashboards and reports.

mml
task "Revenue Dashboard" {
  builds "Sales Analytics.Revenue Dashboard"
  depends_on "Build Customer Entity"
  depends_on "Build Order Entity"
  assignee = "charlie"
  status = "not-started"
}

Attributes:

  • builds: Reference to report ("ProductName.ReportName")
  • depends_on: Task dependencies (optional, auto-suggested)
  • assignee: Person responsible (optional)
  • status: Task status (default: "not-started")
  • manual_hours: Override estimated hours (optional)
  • notes: Task notes (optional)

Hour estimation: Pulled from report_estimate or default (8 hours)

Auto-suggested dependencies:

  • All entities referenced in report metrics (via uses statements)

Component Tasks

Tasks for specialized data product components.

mml
task "Customer API Endpoint" {
  builds "Customer 360.customer_api"
  component_type = "api"
  depends_on = "Build Customer Entity"
  assignee = "diana"
  status = "not-started"
}

Component types:

  • report: BI dashboards (8 hours default)
  • cube: OLAP cubes (16 hours default)
  • metric: Standalone KPIs (4 hours default)
  • reverse-etl: Data sync to operational systems (12 hours default)
  • api: Programmatic access endpoints (10 hours default)
  • stream: Real-time data streams (14 hours default)

Attributes:

  • builds: Reference to component ("ProductName.ComponentName")
  • component_type: Component type (required)
  • depends_on: Task dependencies (optional, auto-suggested)
  • assignee: Person responsible (optional)
  • status: Task status (default: "not-started")
  • manual_hours: Override estimated hours (optional)
  • notes: Task notes (optional)

Hour estimation: Default hours by component type

Auto-suggested dependencies:

  • All entities referenced in the component

Data Product Tasks

Tasks for packaging complete data products.

mml
task "Launch Sales Analytics" {
  builds "Sales Analytics"
  depends_on "Revenue Dashboard"
  depends_on "Customer Insights Report"
  assignee = "eve"
  status = "not-started"
}

Attributes:

  • builds: Reference to data product ("ProductName")
  • depends_on: Task dependencies (required - typically all reports)
  • assignee: Person responsible (optional)
  • status: Task status (default: "not-started")
  • manual_hours: Override estimated hours (optional)
  • notes: Task notes (optional)

Hour estimation: Default (16 hours)

Auto-suggested dependencies: None (manually specify report dependencies)

Scheduling Algorithm

Date Calculation

For each task in order:

1. If task has dependencies:
   start_date = MAX(end_date of all dependencies)

2. Else if not first task:
   start_date = end_date of previous task

3. Else:
   start_date = roadmap.start_date

4. Calculate duration:
   days_required = CEIL(estimated_hours / (team_size * hours_per_day))

5. Calculate end date:
   end_date = start_date + days_required

Example Calculation

Given:

  • Team size: 2 people
  • Hours per day: 6 hours/person/day
  • Capacity: 2 × 6 = 12 hours/day

Task 1: Build Customer (48 hours)

days_required = CEIL(48 / 12) = 4 days
start_date = 2025-01-01
end_date = 2025-01-05

Task 2: Build Order (40 hours, depends on Customer)

days_required = CEIL(40 / 12) = 4 days
start_date = 2025-01-05 (Customer's end_date)
end_date = 2025-01-09

Task 3: Revenue Dashboard (68 hours, depends on Customer + Order)

days_required = CEIL(68 / 12) = 6 days
start_date = 2025-01-09 (MAX of dependencies)
end_date = 2025-01-15

Complete Example

mml
# Configure roadmap
roadmap {
  start_date = "2025-01-01"
  team_size = 2
  hours_per_day = 6
}

# Define entities with estimates
domain "Sales" {
  entity "Customer" {
    type = "entity"
    description = "Customer master data"
  }

  entity "Order" {
    type = "entity"
    description = "Sales orders"
  }
}

entity_estimate "Sales.Customer" {
  data_quality = "medium"
  data_volume = "large"
  scd_type = "type-2"
  business_rules_complexity = "moderate"
  requires_resolution = false
  derivation_count = 3
  kpi_count = 2
  testing_effort = 8
  # Calculated: ~120 hours
}

entity_estimate "Sales.Order" {
  data_quality = "high"
  data_volume = "very-large"
  scd_type = "type-1"
  business_rules_complexity = "simple"
  requires_resolution = false
  derivation_count = 2
  kpi_count = 1
  testing_effort = 4
  # Calculated: ~72 hours
}

# Define sources with estimates
source_estimate "PostgreSQL_Production" {
  source_complexity = "simple"
  data_volume = "large"
  refresh_frequency = "hourly"
  requires_auth = false
  requires_transformation = false
  # Calculated: ~10 hours
}

# Define data product
data_product "Sales Analytics" {
  owner = "sales-team"

  report "Revenue Dashboard" {
    type = "dashboard"

    uses "Sales.Customer"
    uses "Sales.Order"

    metric "Total Revenue" {
      calculation = "SUM(Order.amount)"
      uses "Sales.Order"
    }

    metric "Customer Count" {
      calculation = "COUNT(DISTINCT Customer.id)"
      uses "Sales.Customer"
    }
  }
}

report_estimate "Sales Analytics.Revenue Dashboard" {
  report_complexity = "moderate"
  visualization_count = 8
  interactivity_level = "basic"
  requires_custom_design = false
  # Calculated: ~112 hours
}

# Define roadmap tasks
task "Setup Database Connection" {
  builds "PostgreSQL_Production"
  assignee = "alice"
  status = "completed"
  notes = "PostgreSQL read-only user configured"
  # Hours: 10, Days: 1 (10/12), Start: 2025-01-01, End: 2025-01-02
}

task "Build Customer Entity" {
  builds "Sales.Customer"
  depends_on "Setup Database Connection"
  assignee = "alice"
  status = "in-progress"
  # Hours: 120, Days: 10 (120/12), Start: 2025-01-02, End: 2025-01-12
}

task "Build Order Entity" {
  builds "Sales.Order"
  depends_on "Setup Database Connection"
  assignee = "bob"
  status = "not-started"
  # Hours: 72, Days: 6 (72/12), Start: 2025-01-02, End: 2025-01-08
}

task "Create Revenue Dashboard" {
  builds "Sales Analytics.Revenue Dashboard"
  depends_on "Build Customer Entity"  # auto-suggested
  depends_on "Build Order Entity"     # auto-suggested
  assignee = "charlie"
  status = "not-started"
  notes = "Requires both Customer and Order entities"
  # Hours: 112, Days: 10 (112/12), Start: 2025-01-12, End: 2025-01-22
}

task "Launch Sales Analytics" {
  builds "Sales Analytics"
  depends_on "Create Revenue Dashboard"
  assignee = "alice"
  status = "not-started"
  # Hours: 16, Days: 2 (16/12), Start: 2025-01-22, End: 2025-01-24
}

# Total project duration: 2025-01-01 to 2025-01-24 (24 days)
# Critical path: Setup → Customer → Dashboard → Launch

Dependency Management

Automatic Dependencies

Modality automatically suggests dependencies based on your data model:

For Entities:

mml
domain "Sales" {
  entity "Customer" {
    type = "entity"
  }

  entity "Order" {
    type = "entity"
    contains entity.Customer  # Relationship defined
  }
}

# Auto-suggested dependency:
task "Build Order" {
  builds "Sales.Order"
  depends_on "Build Customer"  # ← Automatically suggested
}

For Reports:

mml
report "Revenue Dashboard" {
  metric "Total Revenue" {
    uses "Sales.Order"     # Entity reference
  }
  metric "Customer Count" {
    uses "Sales.Customer"  # Entity reference
  }
}

# Auto-suggested dependencies:
task "Revenue Dashboard" {
  builds "Sales Analytics.Revenue Dashboard"
  depends_on "Build Order"     # ← Auto from uses
  depends_on "Build Customer"  # ← Auto from uses
}

Manual Dependencies

Override or add custom dependencies:

mml
task "Build Customer 360" {
  builds "Analytics.Customer360"

  # Manual dependencies for specific reasons
  depends_on "Build Customer"
  depends_on "Build Order"
  depends_on "Build Support Ticket"
  depends_on "Setup Salesforce API"

  notes = "Requires all customer touchpoint data"
}

Complex Dependency Chains

Dependencies create critical paths:

mml
# Foundation
task "Setup Infrastructure" {
  builds "AWS_Account"
  manual_hours = 40
}

# Data sources (parallel)
task "Integrate CRM" {
  builds "Salesforce_API"
  depends_on "Setup Infrastructure"
}

task "Integrate Database" {
  builds "PostgreSQL_Production"
  depends_on "Setup Infrastructure"
}

# Entities (parallel after sources)
task "Build Customer" {
  builds "Sales.Customer"
  depends_on "Integrate CRM"
  depends_on "Integrate Database"
}

task "Build Product" {
  builds "Sales.Product"
  depends_on "Integrate Database"
}

task "Build Order" {
  builds "Sales.Order"
  depends_on "Integrate Database"
  depends_on "Build Customer"  # Logical dependency
  depends_on "Build Product"   # Logical dependency
}

# Reports (after all entities)
task "Customer Dashboard" {
  builds "Sales Analytics.Customer Dashboard"
  depends_on "Build Customer"
  depends_on "Build Order"
}

task "Product Dashboard" {
  builds "Sales Analytics.Product Dashboard"
  depends_on "Build Product"
  depends_on "Build Order"
}

# Final product (after all reports)
task "Launch Sales Analytics" {
  builds "Sales Analytics"
  depends_on "Customer Dashboard"
  depends_on "Product Dashboard"
}

Critical path: Setup → Integrate → Build Order → Dashboards → Launch

Task Status Tracking

Status Values

  • not-started: Task hasn't begun (default)
  • in-progress: Task is actively being worked on
  • completed: Task is finished

Updating Status

mml
task "Build Customer" {
  builds "Sales.Customer"
  status = "in-progress"  # Current status
  assignee = "alice"
  notes = """
    Started: 2025-01-05
    40% complete as of 2025-01-08
    Blocked: Waiting for CRM API access
  """
}

Progress Tracking

Use notes to track progress:

mml
task "Revenue Dashboard" {
  builds "Sales Analytics.Revenue Dashboard"
  status = "in-progress"
  notes = """
    Week 1: Completed mockups and design
    Week 2: Built 5 of 8 visualizations
    Remaining: 3 charts, testing, documentation
    Expected completion: 2025-01-22
  """
}

Best Practices

1. Start with Foundational Tasks

Order tasks logically:

mml
# ✅ Good order
task "Setup Infrastructure" { ... }      # First
task "Integrate Sources" { ... }         # Second
task "Build Core Entities" { ... }       # Third
task "Build Derived Entities" { ... }    # Fourth
task "Create Reports" { ... }            # Fifth
task "Launch Product" { ... }            # Last

2. Be Realistic with Team Capacity

Don't overestimate availability:

mml
# ✅ Realistic
roadmap {
  team_size = 2
  hours_per_day = 6  # Accounts for meetings, interruptions
}

# ❌ Unrealistic
roadmap {
  team_size = 2
  hours_per_day = 10  # Nobody can sustain this
}

3. Use Manual Hours for Uncertainty

Override estimates when you have better information:

mml
task "Migrate Legacy System" {
  builds "Legacy.MainframeData"
  manual_hours = 200  # Known to be complex
  notes = "Previous migration took 3 weeks with similar scope"
}

4. Document Blockers and Risks

Use notes to track issues:

mml
task "Build Customer 360" {
  builds "Analytics.Customer360"
  status = "in-progress"
  notes = """
    BLOCKER: Waiting for legal approval on PII handling
    RISK: CRM API rate limits may cause delays
    RISK: Data quality worse than expected
  """
}

5. Update as You Learn

Adjust estimates and dependencies:

mml
task "Build Order Entity" {
  builds "Sales.Order"
  manual_hours = 120  # Originally 72
  notes = """
    Original estimate: 72 hours
    Revised: 120 hours after discovering:
    - Complex tax calculation logic
    - Multi-currency support needed
    - Promo code validation required
  """
}

6. Parallel vs. Sequential Work

Structure tasks to maximize parallelism:

mml
# ✅ Good - parallel work
task "Build Customer" {
  builds "Sales.Customer"
  assignee = "alice"
}

task "Build Product" {
  builds "Sales.Product"
  assignee = "bob"  # Can work in parallel
}

# ❌ Bad - artificial sequencing
task "Build Customer" {
  builds "Sales.Customer"
}

task "Build Product" {
  builds "Sales.Product"
  depends_on "Build Customer"  # Unnecessary dependency
}

7. Group Similar Work

Assign related tasks to same person:

mml
task "Build Customer" {
  builds "Sales.Customer"
  assignee = "alice"
}

task "Build Order" {
  builds "Sales.Order"
  assignee = "alice"  # Same domain, same person
}

task "Customer Dashboard" {
  builds "Analytics.Customer Dashboard"
  assignee = "bob"  # Different specialty (BI)
}

Roadmap Visualization

Modality displays roadmaps as Gantt charts showing:

  • Task bars: Duration and scheduling
  • Dependencies: Arrows between tasks
  • Critical path: Longest path through dependencies
  • Progress: Color-coded by status
  • Assignments: Who's working on what
  • Timeline: Day/week/month/quarter views

Timeline views:

  • Day view: Detailed daily scheduling
  • Week view: Weekly sprints
  • Month view: Monthly milestones
  • Quarter view: High-level quarterly planning

Summary

Roadmapping in Modality provides:

Automatic scheduling based on estimates and capacity ✅ Intelligent dependencies from your data model ✅ Visual timeline with Gantt charts ✅ Progress tracking with statuses ✅ Flexible overrides for custom scenarios ✅ Team capacity planning with realistic timelines

By combining estimation, dependencies, and team capacity, Modality creates realistic project timelines that adapt as your understanding improves.

Released under the MIT License.