HomeGuides › Gantt Chart Dependencies Explained: FS, SS, FF and SF

Gantt Chart Dependencies Explained: FS, SS, FF and SF

Four relationship types cover every dependency you can draw on a Gantt chart. One does about ninety per cent of the work; the other three exist for the cases it handles badly. Here is what each means, worked through one real project, plus the two things most explanations skip: lag versus lead, and total versus free float.

· gantts.app

The four dependency types, shown as they behave on a chart:
Finish → Start (FS) B cannot start until A finishes — the default A B Start → Start (SS) B cannot start until A starts A B Finish → Finish (FF) B cannot finish until A finishes A B Start → Finish (SF) B cannot finish until A starts — rare A B

The project we will use throughout

Dependency diagrams are easy to nod along to and hard to apply. So: one real project — a billing system cutover — that every type below is applied to.

Replace the billing system. Six tasks, working days, March–April 2026.

#TaskStartEndDays
1Build the migration scriptsMon 2 MarFri 13 Mar10 days
2Dry-run the migrationMon 16 MarFri 20 Mar5 days
3Fix the defects the dry run findsMon 23 MarFri 3 Apr10 days
4Write the cutover runbookMon 16 MarFri 3 Apr15 days
5Train the billing teamMon 23 MarFri 27 Mar5 days
6Keep the legacy system runningMon 2 MarMon 6 Apr26 days

Six bars, no links yet — nothing here says what depends on what.

Finish-to-Start (FS) — the one you will use

Task B cannot start until task A finishes: pour the foundation, then frame the walls.

Task 2 is FS after task 1: you cannot dry-run a script nobody has written. Task 3 is FS after task 2, because the defect list does not exist until the dry run produces it. That chain — 1 → 2 → 3 — is the spine of the project and sets the 3 April finish.

FS is the default in every scheduling tool, and if you are unsure it is almost certainly right. Reaching for an exotic type usually means the tasks are wrongly broken down.

Start-to-Start (SS) — work that runs together

Task B cannot start until task A starts, and the two then run in parallel.

The runbook (task 4) is SS after the dry run. The writer needs the dry run underway to have anything to document, but waiting for it to finish would waste a week — so both begin Monday 16 March. The tell for SS is a shared trigger, not a shared deadline.

Finish-to-Finish (FF) — work that must land together

Task B cannot finish until A finishes.

The runbook also has an FF link to task 3: it cannot be signed off while defects are still landing, because each fix rewrites a step in it. So it stays open until Friday 3 April — started by the dry run, closed by the fixes, which is the shape of a support activity. Testing, documentation and QA sign-off are all FF for the same reason: B may start whenever, it just cannot cross the line first.

Start-to-Finish (SF) — the rare one

Task B cannot finish until task A starts. It reads backwards, and most planners never need it.

Task 6 is the case it was invented for. The legacy system must run until the new one is live: its finish is pinned to go-live's start. Link it SF and the legacy bar stretches to meet whatever date go-live lands on.

That is the test: a handover, where the outgoing thing ends because the incoming one begins. Anywhere else, reordering the tasks usually says the same thing with a plain FS.

The four types side by side

TypeReal-world triggerHow often it appliesThe mistake it invites
FS
Finish → Start
A's output is B's input — a defect list, a signed drawing, a poured slab~90% of linksUsed for preference, not constraint, until every date is pinned
SS
Start → Start
Two activities share a trigger, then run togetherCommon; most plans have a fewReacts only to the predecessor's start: if A's finish slips, B never moves
FF
Finish → Finish
A wrapper that cannot close before the work it wraps — testing, docs, sign-offOccasional, mostly support tasksB's start left unconstrained, so it looks able to begin absurdly early
SF
Start → Finish
A handover — the old shift or system ends because the new one beginsRare; many correct plans have noneA clumsy backwards FS that reviewers misread

When the wrong type makes the schedule lie

Now task 5, training. A planner links it SS after task 3: training starts when defect-fixing starts. It looks fine — both bars begin 23 March, everyone trained by 27 March, well before go-live.

Then the dry run finds more than expected. Task 3 grows from 10 days to 15, pushing its finish from Fri 3 Apr to Fri 10 Apr.

  • Task 4 (runbook, FF) — moves. Its finish follows to Fri 10 Apr. Correct.
  • Task 5 (training, SS)does not move at all. SS watches the predecessor's start, and the start did not change. The plan still shows the team trained on Fri 27 Mar.

The chart is not broken; it is answering the question it was asked. But the team is now trained on software with a fortnight of defects still to land, and the plan reports that as green. The right link was FS after task 3. One wrong letter turned a two-week problem into no problem at all.

So test for it: extend the task most likely to overrun by a week, and see what moved. Anything you expected to shift and did not is a wrong type.

Lag and lead — a lag is a wait, not slack

A lag adds waiting time to a link. "FS + 3 days" means B starts three days after A finishes. Here, go-live is FS+1d after the defect fixes: one clear day for a final data sync.

Finish → Start + LagALag 3dBB waits for A + 3d
A lag is committed waiting time inside the link, not spare room around it.

The thing people get wrong: a lag is not slack. Slack is room you can spend when something slips. A lag is time already committed — concrete curing, paint drying, a contractual review window — and nobody gets to "use" it when they run late. Padding links with lag because a task "might" overrun creates contingency nobody can find or cut.

A lead is negative lag: "FS − 2 days" overlaps the tail of A. Leads compress a schedule — this is what fast-tracking is — but they buy time with risk. An overlap you have not reasoned about is a rework queue.

Both are written 3FS+2d — row 3, finish-to-start, two days lag — which gantts.app takes in the Runs after column.

Total float and free float are not the same number

Every task now has float: how long it can slip before it hurts something. There are two kinds, and confusing them is expensive.

ABCFree floatTotal float
Total float belongs to the chain. Free float belongs to the task.

Total float is how far a task can slip before the project finish moves. Free float is how far before its own successor moves. Free float is never larger.

Training has total float — the finish date is set by the defect chain. But total float is shared: if three tasks in a row each show eight days, there are eight days between them, not twenty-four. A lead who reads only that number and delays a week has spent float belonging to the whole chain.

A · 3B · 5C · 2D · 4Critical path: A → B → DSlack (C): 3Duration: 12
Zero total float means critical: every day of slip moves the finish date.

Total float of zero is the definition of the critical path. Tick Critical path in gantts.app and that chain draws striped. That is where the types have to be right.

Creating and editing a dependency in gantts.app

  1. Drag from bar to bar. Grab the small dot at the edge of a task bar, drag onto the bar you want to link and release. The link is created as FS with zero lag.
  2. Change its type. Click the arrow between the bars. The link editor opens with a Type dropdown: FS · Finish → Start, SS · Start → Start, FF · Finish → Finish, SF · Start → Finish.
  3. Add a lag. Same editor, Lag (days) field: 1 for the FS+1d before go-live, a negative number for a lead. Both undo with Ctrl+Z.
  4. Or type it. The grid's Runs after column takes predecessors by row number: 3, 2SS, 3FF, 3FS+2d, comma-separated. Fastest way to link a plan you just pasted in.
  5. Or use the task card. Click a task, open Runs after (predecessors), and pick from the + Start this after… dropdown. Each existing link has its own type selector.
  6. Remove one. 🗑 Remove this link in the link editor, or the ✕ in the task card.

One behaviour worth knowing: adding a dependency here can only push a task later, never pull it earlier. The scheduler is "as-placed" — a task starts at the later of where you dragged it and where its predecessors allow. Link a task whose bar already sits well after its predecessor and nothing moves; the gap stays, because a bar you placed on purpose should not be yanked about by a link added for reporting. To compact everything, press ⚡ Auto-schedule, which pulls each dependent task back to the earliest date its predecessors allow, leaving unlinked tasks as anchors.

A dependency should describe a real constraint, not a preference. "We would rather do B after A" is a sequencing choice and belongs in the ordering; "B cannot start until A is done" is a dependency. Charts full of the former cannot be re-planned: every date is pinned by something that was never mandatory.

Templates that use this

Frequently asked questions

What are the 4 types of dependencies in a Gantt chart?

Finish-to-Start (FS), Start-to-Start (SS), Finish-to-Finish (FF) and Start-to-Finish (SF). FS covers the large majority of real relationships; SF is rare, and many plans need none.

What is the difference between lead and lag?

Lag is waiting time added to a link: FS+3d starts the successor three days after the predecessor finishes. Lead is negative lag, overlapping the two. A lag is committed time, not spare room.

What is the difference between total float and free float?

Total float is how far a task can slip before the project finish moves; free float is how far before its own successor moves. Total float is shared along a chain: three tasks each showing eight days do not have twenty-four between them.

Which dependency type should I use by default?

Finish-to-Start. If another type seems necessary, check whether the tasks are broken down correctly — an unusual type is often a symptom of a task that should be split.

What happens to my dates when I add a dependency in gantts.app?

A dependency can only push a task later, never pull it earlier: a task starts at the later of where you placed it and where its predecessors allow. Press ⚡ Auto-schedule to compact tasks back to their earliest legal dates.

How do I add dependencies in gantts.app?

Drag from the dot at the edge of a task bar onto another bar, or type notation such as 3FS+2d in the Runs after column. Click a link arrow to change its Type or Lag.

Try it on your own plan

gantts.app is a free Gantt chart maker that runs in your browser. No account, no download, no watermark on exports.

Open the free editor