17. Due Date Support

User Tasks can have due dates — deadlines that indicate when a task should be completed. Workingflow reads this information from the BPMN definition and highlights overdue tasks automatically.

How It Works

Aspect Details
Set in Camunda Modeler → User Task Properties → "Due Date" field
BPMN attribute flowable:dueDate
Accepts Fixed date, ISO 8601 duration, or process variable expression
Overdue display Task row turns red in My Tasks and All Tasks views

[!IMPORTANT] Due dates are never enforced — they are informational. An overdue task can still be completed normally. The red highlight simply draws attention to tasks that need urgent action.


Scenario 1: Fixed Duration After Task Creation

The most common use case. The task gets a deadline relative to when it was created.

Set in the Due Date field of the User Task:

P3D

This means "3 days after the task is assigned." When the task is created, Flowable automatically calculates the due date.

Common duration formats (ISO 8601):

Duration Meaning
PT1H 1 hour
PT24H 24 hours
P1D 1 day
P3D 3 days
P1W 1 week
P2W 2 weeks
P1M 1 month
PT2H30M 2 hours 30 minutes

BPMN XML:

<userTask id="approveRequest" name="Approve Request"
          flowable:assignee="${manager}"
          flowable:dueDate="P3D">
</userTask>

Scenario 2: Fixed Date (Static)

For tasks with a specific known deadline. The date must be in ISO 8601 format.

Set in the Due Date field:

2026-06-15T17:00:00

Accepted date formats:

Format Example
Full datetime 2026-06-15T17:00:00
Date only 2026-06-15

BPMN XML:

<userTask id="submitReport" name="Submit Annual Report"
          flowable:assignee="${accountant}"
          flowable:dueDate="2026-06-15T17:00:00">
</userTask>

Scenario 3: Date From a Form Variable

A previous form collects a deadline date from the user, and a later task uses that date as its due date.

Step 1: Collect the deadline in a Start Form or User Task:

<userTask id="submitRequest" name="Submit Request" flowable:assignee="${initiator}">
    <extensionElements>
        <activiti:formProperty id="description" name="Description" type="string" required="true"/>
        <activiti:formProperty id="requestedDeadline" name="Deadline" type="date" required="true"/>
    </extensionElements>
</userTask>

Step 2: Reference the variable in the next task's Due Date:

<userTask id="approveRequest" name="Approve Request"
          flowable:assignee="${manager}"
          flowable:dueDate="${requestedDeadline}">
</userTask>

The ${requestedDeadline} expression reads the date variable set by the previous form. Flowable resolves it when the task is created.


Scenario 4: Date Variable + Duration Offset (Script Task)

When you need "a date from a form + some extra days," you must compute it with a Script Task because the Due Date field does not support arithmetic expressions.

Example: User enters a preferred deadline, but the approval task gets 2 extra days.

<!-- Step 1: User enters a deadline -->
<userTask id="submitRequest" name="Submit Request" flowable:assignee="${initiator}">
    <extensionElements>
        <activiti:formProperty id="preferredDeadline" name="Preferred Deadline" type="date" required="true"/>
    </extensionElements>
</userTask>

<sequenceFlow sourceRef="submitRequest" targetRef="calcDeadline"/>

<!-- Step 2: Calculate due date with offset -->
<scriptTask id="calcDeadline" name="Calculate Due Date" scriptFormat="super-js">
  <script>
    var preferred = execution.getVariable('preferredDeadline');
    var approvalDeadline = wf.addDays(preferred, 2);
    execution.setVariable('approvalDueDate', approvalDeadline);
  </script>
</scriptTask>

<sequenceFlow sourceRef="calcDeadline" targetRef="approveRequest"/>

<!-- Step 3: Use the calculated date -->
<userTask id="approveRequest" name="Approve Request"
          flowable:assignee="${manager}"
          flowable:dueDate="${approvalDueDate}">
</userTask>

Tip: Use wf.addBusinessDays() instead of wf.addDays() if you want to skip weekends.


Scenario 5: Process Start Date + Duration (Script Task)

When the deadline should be relative to when the process started, not when the task was created.

<!-- Calculate deadline: process start + 5 business days -->
<scriptTask id="calcDeadline" name="Calculate Deadline" scriptFormat="super-js">
  <script>
    var startDate = wf.getProcessStartDate(execution);
    var deadline = wf.addBusinessDays(startDate, 5);
    execution.setVariable('processDeadline', deadline);
  </script>
</scriptTask>

<sequenceFlow sourceRef="calcDeadline" targetRef="reviewTask"/>

<userTask id="reviewTask" name="Review Document"
          flowable:assignee="${reviewer}"
          flowable:dueDate="${processDeadline}">
</userTask>

Scenario 6: Dynamic Duration From a Form Field (Script Task)

When the number of days itself comes from user input (e.g., "How many days should approval take?").

<!-- User specifies the SLA -->
<userTask id="configure" name="Configure SLA" flowable:assignee="${initiator}">
    <extensionElements>
        <activiti:formProperty id="slaDays" name="Approval SLA (days)" type="long" required="true"/>
    </extensionElements>
</userTask>

<sequenceFlow sourceRef="configure" targetRef="calcSla"/>

<!-- Calculate due date from dynamic input -->
<scriptTask id="calcSla" name="Calculate SLA Deadline" scriptFormat="super-js">
  <script>
    var days = execution.getVariable('slaDays');
    var deadline = wf.addDays(wf.now(), days);
    execution.setVariable('slaDueDate', deadline);
  </script>
</scriptTask>

<sequenceFlow sourceRef="calcSla" targetRef="approveTask"/>

<userTask id="approveTask" name="Approve"
          flowable:assignee="${manager}"
          flowable:dueDate="${slaDueDate}">
</userTask>

Overdue Display

Tasks with a due date that has passed are automatically highlighted with a red row in both the My Tasks and All Tasks views. No configuration is needed — if the task has a due date and it is in the past, the row turns red.

State Display
No due date set Normal row
Due date in the future Normal row
Due date has passed Red row (table-danger)

Overdue Email Notifications

Due dates on their own are passive — the red row is only visible when a user opens the task list. To proactively notify users when a deadline is reached, combine the due date with a non-interrupting boundary timer event and the ${sendReminder} delegate.

The boundary timer fires at the exact deadline moment and sends an email, while the task stays open for the user to complete.

Example 1: Static 3-day SLA with overdue notification

<userTask id="approve" name="Approve Request"
          flowable:assignee="${manager}"
          flowable:dueDate="P3D">
</userTask>

<!-- Non-interrupting boundary timer: fires when the due date is reached -->
<boundaryEvent id="overdueAlert" attachedToRef="approve" cancelActivity="false">
    <timerEventDefinition>
        <timeDuration>P3D</timeDuration>
    </timerEventDefinition>
</boundaryEvent>

<sequenceFlow sourceRef="overdueAlert" targetRef="sendOverdueEmail"/>

<serviceTask id="sendOverdueEmail" flowable:delegateExpression="${sendReminder}">
    <extensionElements>
        <flowable:field name="to" expression="${manager}"/>
        <flowable:field name="subject" stringValue="Task Overdue: Approve Request"/>
        <flowable:field name="body" stringValue="Your approval task has passed its deadline. Please take action."/>
    </extensionElements>
</serviceTask>

Example 2: Dynamic deadline from a form variable

When the due date comes from a computed variable (e.g., via Script Task), use <timeDate> with the same variable:

<userTask id="review" name="Review Document"
          flowable:assignee="${reviewer}"
          flowable:dueDate="${calculatedDeadline}">
</userTask>

<!-- Timer fires at the exact calculated deadline -->
<boundaryEvent id="reviewOverdue" attachedToRef="review" cancelActivity="false">
    <timerEventDefinition>
        <timeDate>${calculatedDeadline}</timeDate>
    </timerEventDefinition>
</boundaryEvent>

<sequenceFlow sourceRef="reviewOverdue" targetRef="notifyReviewOverdue"/>

<serviceTask id="notifyReviewOverdue" flowable:delegateExpression="${sendReminder}">
    <extensionElements>
        <flowable:field name="to" expression="${reviewer}"/>
        <flowable:field name="subject" stringValue="Review Deadline Passed"/>
        <flowable:field name="body" stringValue="The review task has passed its deadline."/>
    </extensionElements>
</serviceTask>

Example 3: Repeating reminders after deadline

Send a reminder email every day after the deadline until the task is completed:

<boundaryEvent id="dailyNag" attachedToRef="approve" cancelActivity="false">
    <timerEventDefinition>
        <!-- Wait for the due date, then repeat daily -->
        <timeCycle>R/P3D/P1D</timeCycle>
    </timerEventDefinition>
</boundaryEvent>

[!TIP] The boundary timer and flowable:dueDate are independent features — they just happen to work perfectly together. The due date controls the red row in the UI. The boundary timer controls the email notification. You can use either one alone, or combine them for maximum effect.


Quick Reference

What You Want Due Date Field Value Script Task Needed?
3 days after task creation P3D No
24 hours after task creation PT24H No
Specific fixed date 2026-06-15T17:00:00 No
Date from a form variable ${myDateVariable} No
Form date + extra days ${calculatedDate} Yes — use wf.addDays()
Process start + N days ${calculatedDate} Yes — use wf.getProcessStartDate() + wf.addDays()
Dynamic days from user input ${calculatedDate} Yes — use wf.addDays(wf.now(), days)