TechLead
Lesson 3 of 30
6 min read
Project Management

Waterfall Methodology

Learn the sequential Waterfall approach, when it works best, its phases, strengths, weaknesses, and real-world applications

What Is Waterfall?

The Waterfall methodology is a sequential, linear approach to project management where each phase must be completed before the next begins. Introduced by Winston Royce in 1970 (though he actually advocated for iterative approaches), Waterfall became the dominant methodology for decades, especially in hardware engineering, construction, and regulated software development.

In Waterfall, requirements are gathered upfront, a comprehensive design is created, the system is built according to the design, testing verifies the build, and finally the system is deployed and maintained. Each phase flows downward like a waterfall, with no going back.

The Five Waterfall Phases

  1. 1. Requirements: Gather all requirements upfront. Produce a comprehensive Software Requirements Specification (SRS) document. Stakeholders sign off before moving forward.
  2. 2. Design: Create system architecture and detailed design documents. Database schemas, API contracts, UI wireframes, and infrastructure diagrams are finalized.
  3. 3. Implementation: Developers write code according to the design specifications. This is the longest phase, consuming 40-60% of the project timeline.
  4. 4. Verification (Testing): QA team performs comprehensive testing: unit, integration, system, and user acceptance testing. Defects are logged and fixed.
  5. 5. Maintenance: The system is deployed to production. Ongoing bug fixes, patches, and minor enhancements are handled post-launch.

When Waterfall Works Well

Despite its reputation in the Agile era, Waterfall remains the right choice in specific contexts:

Ideal Waterfall Scenarios

  • Regulated Industries: Healthcare (FDA), aviation (DO-178C), finance (SOX compliance) require extensive documentation and traceability that Waterfall naturally provides.
  • Fixed Requirements: When requirements are well-understood and unlikely to change (e.g., migrating a legacy system with identical functionality).
  • Hardware Integration: Projects with hardware components that cannot be easily changed once manufactured.
  • Contract Work: Fixed-price contracts where scope must be precisely defined upfront to avoid disputes.
  • Safety-Critical Systems: Embedded systems, medical devices, or aerospace where exhaustive testing before deployment is non-negotiable.

Waterfall Strengths vs. Weaknesses

Strengths Weaknesses
Clear structure and milestonesLate discovery of issues (testing at the end)
Comprehensive documentationInflexible to requirement changes
Easy to understand and manageCustomer sees the product only at the end
Predictable timeline and budgetAssumes requirements can be fully known upfront
Well-suited for compliance and auditsHigh risk of building the wrong thing
Clear handoffs between teamsLong time to market (no early delivery)
Works well with distributed teamsMorale issues from late-stage rework

Waterfall Project Plan Data Structure

// Waterfall Project Plan Data Model
interface WaterfallPhase {
  name: string;
  startDate: Date;
  endDate: Date;
  status: 'not-started' | 'in-progress' | 'completed' | 'blocked';
  deliverables: Deliverable[];
  gateReview: GateReview;
  dependencies: string[]; // previous phase names
}

interface Deliverable {
  name: string;
  type: 'document' | 'code' | 'artifact' | 'sign-off';
  assignee: string;
  status: 'draft' | 'review' | 'approved' | 'rejected';
  approvers: string[];
  dueDate: Date;
}

interface GateReview {
  reviewDate: Date;
  reviewers: string[];
  criteria: string[];
  decision: 'pass' | 'fail' | 'conditional' | 'pending';
  conditions?: string[];
}

// Complete Waterfall project plan
const waterfallProject: WaterfallPhase[] = [
  {
    name: 'Requirements',
    startDate: new Date('2024-01-15'),
    endDate: new Date('2024-03-01'),
    status: 'completed',
    deliverables: [
      {
        name: 'Software Requirements Specification (SRS)',
        type: 'document',
        assignee: 'Business Analyst',
        status: 'approved',
        approvers: ['Product Owner', 'Tech Lead', 'QA Lead'],
        dueDate: new Date('2024-02-15')
      },
      {
        name: 'Requirements Traceability Matrix',
        type: 'document',
        assignee: 'Business Analyst',
        status: 'approved',
        approvers: ['Project Manager', 'QA Lead'],
        dueDate: new Date('2024-02-28')
      },
      {
        name: 'Stakeholder Sign-off',
        type: 'sign-off',
        assignee: 'Project Manager',
        status: 'approved',
        approvers: ['Project Sponsor', 'VP Engineering'],
        dueDate: new Date('2024-03-01')
      }
    ],
    gateReview: {
      reviewDate: new Date('2024-03-01'),
      reviewers: ['Project Sponsor', 'VP Engineering', 'Product Owner'],
      criteria: [
        'All functional requirements documented and prioritized',
        'Non-functional requirements defined with measurable targets',
        'Requirements traceability matrix complete',
        'Stakeholder sign-off obtained'
      ],
      decision: 'pass'
    },
    dependencies: []
  },
  {
    name: 'Design',
    startDate: new Date('2024-03-04'),
    endDate: new Date('2024-04-15'),
    status: 'completed',
    deliverables: [
      {
        name: 'System Architecture Document',
        type: 'document',
        assignee: 'Solution Architect',
        status: 'approved',
        approvers: ['Tech Lead', 'VP Engineering'],
        dueDate: new Date('2024-03-22')
      },
      {
        name: 'Database Design (ERD)',
        type: 'artifact',
        assignee: 'Database Architect',
        status: 'approved',
        approvers: ['Tech Lead'],
        dueDate: new Date('2024-04-01')
      },
      {
        name: 'UI/UX Mockups',
        type: 'artifact',
        assignee: 'UX Designer',
        status: 'approved',
        approvers: ['Product Owner', 'Frontend Lead'],
        dueDate: new Date('2024-04-10')
      }
    ],
    gateReview: {
      reviewDate: new Date('2024-04-15'),
      reviewers: ['Tech Lead', 'VP Engineering', 'QA Lead'],
      criteria: [
        'Architecture addresses all non-functional requirements',
        'API contracts defined for all services',
        'Security review completed',
        'Design reviewed for testability'
      ],
      decision: 'pass'
    },
    dependencies: ['Requirements']
  },
  {
    name: 'Implementation',
    startDate: new Date('2024-04-16'),
    endDate: new Date('2024-08-30'),
    status: 'in-progress',
    deliverables: [
      {
        name: 'Backend Services',
        type: 'code',
        assignee: 'Backend Team',
        status: 'review',
        approvers: ['Tech Lead'],
        dueDate: new Date('2024-07-31')
      },
      {
        name: 'Frontend Application',
        type: 'code',
        assignee: 'Frontend Team',
        status: 'draft',
        approvers: ['Tech Lead'],
        dueDate: new Date('2024-08-15')
      },
      {
        name: 'Unit Tests (>80% coverage)',
        type: 'code',
        assignee: 'Dev Team',
        status: 'draft',
        approvers: ['QA Lead'],
        dueDate: new Date('2024-08-30')
      }
    ],
    gateReview: {
      reviewDate: new Date('2024-08-30'),
      reviewers: ['Tech Lead', 'QA Lead'],
      criteria: [
        'All modules implemented per design spec',
        'Unit test coverage >= 80%',
        'Code review completed for all modules',
        'No critical static analysis findings'
      ],
      decision: 'pending'
    },
    dependencies: ['Design']
  }
];

// Calculate phase health
function getPhaseHealth(phase: WaterfallPhase): {
  completionPercentage: number;
  isOnSchedule: boolean;
  blockers: string[];
} {
  const totalDeliverables = phase.deliverables.length;
  const completedDeliverables = phase.deliverables.filter(
    d => d.status === 'approved'
  ).length;

  const today = new Date();
  const totalDays = phase.endDate.getTime() - phase.startDate.getTime();
  const elapsedDays = today.getTime() - phase.startDate.getTime();
  const timeProgress = elapsedDays / totalDays;
  const workProgress = completedDeliverables / totalDeliverables;

  return {
    completionPercentage: Math.round(workProgress * 100),
    isOnSchedule: workProgress >= timeProgress * 0.9,
    blockers: phase.deliverables
      .filter(d => d.status === 'rejected')
      .map(d => `${d.name} rejected - needs rework`)
  };
}

Real-World Example: Medical Device Software

A medical device company building firmware for a blood glucose monitor would use Waterfall because:

  • FDA requires comprehensive documentation (Design History File)
  • Requirements must be traced to test cases for regulatory submission
  • Hardware interfaces are fixed once the device is manufactured
  • Safety-critical calculations must be formally verified
  • Validation testing must cover all documented requirements

Key Takeaway

Waterfall is not dead. It is the wrong choice for most web and mobile application development, but it remains essential for regulated, safety-critical, and hardware-dependent projects. The key is knowing when to use it and when to choose Agile instead.

Waterfall Variants

Several variations of Waterfall have emerged to address its limitations while maintaining its structured approach:

Variant Key Difference Best For
V-ModelEach development phase has a corresponding testing phaseSafety-critical systems with rigorous testing needs
SashimiPhases overlap slightly (like fish slices)Projects needing faster delivery with some flexibility
Incremental WaterfallMultiple waterfalls, each delivering a subset of featuresLarge projects that can be decomposed into independent modules
SpiralCombines Waterfall phases with iterative risk analysisHigh-risk projects where prototyping reduces uncertainty

Continue Learning