# Fairness

> Unfair, weakly fair and strongly fair actions in FizzBee, and why liveness properties need fairness, with runnable examples of each.

Canonical: https://fizzbee.io/reference/language/fairness/
Source: https://github.com/fizzbee-io/fizzbee/blob/main/examples/references/LANGUAGE_REFERENCE.md#fairness


Fairness ensures actions eventually execute under certain conditions.

## Unfair (Default)

No guarantees - action may starve:

```python
action MayStarve:
    counter = counter + 1
    # May never execute even if always enabled
```

## Weak Fairness (`fair` or `fair<weak>`)

Eventually executes if **continuously enabled**:

```python
fair action EventuallyRuns:
    if condition:
        done = True
    # Will execute if condition stays true
```

**Use case**: Actions that should run when persistently enabled

## Strong Fairness (`fair<strong>`)

Eventually executes if **infinitely often enabled**:

```python
fair<strong> action RunsEventually:
    if toggle:
        processed = True
    # Will execute even if toggle alternates
```

**Use case**: Actions enabled intermittently

## Fairness and Liveness

Fairness is required for liveness properties:

```python
fair action Progress:
    counter = counter + 1

eventually always assertion EventuallyDone:
    return counter >= 10
    # Passes because fair action ensures progress
```

## Combining Flow and Fairness Modifiers

Fairness can be combined with flow modifiers (remember: flow modifier comes first):

```python
# Atomic + weak fairness
atomic fair action ProduceMessage:
    require len(queue) < MAX_SIZE
    message = create_message()
    queue.append(message)
    # Executes atomically AND eventually runs if continuously enabled

# Atomic + strong fairness
atomic fair<strong> action ConsumeMessage:
    require len(queue) > 0
    message = queue.pop(0)
    process(message)
    # Executes atomically AND eventually runs if infinitely often enabled

# Serial (default) + weak fairness
fair action BackgroundTask:
    step1 = prepare()  # Yield point
    step2 = execute()  # Yield point
    # Can crash at yield points, but will eventually run if continuously enabled
```

**Important**: The modifier order is always `atomic fair action`, never `fair atomic action`.

## Examples

### Unfair Action (Default) {#unfair-action}

Unfair actions may never execute even if enabled

**Demonstrates:** default unfair behavior, liveness can fail

```fizz
# Example 0043: Unfair Action (Default)
# Unfair actions may never execute even if enabled
# Demonstrates: default unfair behavior, liveness can fail

action Init:
    counter = 0
    progress = False

# Unfair action (default) - no fairness guarantee
action MaybeProgress:
    if counter >= 3:
        progress = True
        return

    counter = counter + 1

# Without fairness, this action might never run
# even though it's always enabled
# Liveness properties may fail

# NOTE: This would fail a liveness check like:
# eventually always assertion EventuallyDone:
#     return progress == True
# Because unfair actions can be ignored forever

atomic action NoOp:
    if counter >= 3:
        pass
```
Run it in the FizzBee playground: https://fizzbee.io/play


**Expected result** (from `fizz`):

```
StateSpaceOptions: options:{max_actions:100 max_concurrent_actions:2}
Nodes: 7, queued: 0
Valid Nodes: 7 Unique states: 7
IsLive: true
PASSED: Model checker completed successfully
```

[Source on GitHub](https://github.com/fizzbee-io/fizzbee/tree/main/examples/references/10-01-unfair-action)

### Weak Fair Action {#weak-fair-action}

Weakly fair actions eventually execute if continuously enabled

**Demonstrates:** fair&lt;weak&gt; or fair (default fairness level)

```fizz
# Example 0044: Weak Fair Action
# Weakly fair actions eventually execute if continuously enabled
# Demonstrates: fair<weak> or fair (default fairness level)

action Init:
    counter = 0
    done = False

# Weakly fair action
fair action Progress:
    if counter >= 3:
        done = True
        return

    counter = counter + 1

# Weak fairness: if action is CONTINUOUSLY enabled,
# it will eventually execute
# Guarantees progress for always-enabled actions

eventually always assertion EventuallyDone:
    return done == True

# With weak fairness, this passes
# Action is continuously enabled until counter>=3

atomic action NoOp:
    if done:
        pass
```
Run it in the FizzBee playground: https://fizzbee.io/play


**Expected result** (from `fizz`):

```
StateSpaceOptions: options:{max_actions:100 max_concurrent_actions:2}
Nodes: 7, queued: 0
Valid Nodes: 7 Unique states: 7
Checking eventually always EventuallyDone
IsLive: true
PASSED: Model checker completed successfully
```

[Source on GitHub](https://github.com/fizzbee-io/fizzbee/tree/main/examples/references/10-02-weak-fair-action)

### Strong Fair Action {#strong-fair-action}

Strongly fair actions execute if infinitely often enabled

**Demonstrates:** fair&lt;strong&gt; for intermittent enabling

```fizz
# Example 0045: Strong Fair Action
# Strongly fair actions execute if infinitely often enabled
# Demonstrates: fair<strong> for intermittent enabling

action Init:
    toggle = True
    processed = False

# Toggle the enabling condition indefinitely
action Toggle:
    toggle = not toggle

# Strongly fair action
fair<strong> action ProcessWhenEnabled:
    require not processed

    # Only enabled when toggle is True
    if toggle:
        processed = True

# Strong fairness: if action is INFINITELY OFTEN enabled,
# it will eventually execute
# Even if intermittently disabled, it will run

# Weak fairness would NOT guarantee this
# because action is not continuously enabled

atomic action NoOp:
    if processed:
        pass
```
Run it in the FizzBee playground: https://fizzbee.io/play


**Expected result** (from `fizz`):

```
StateSpaceOptions: options:{max_actions:100 max_concurrent_actions:2}
Nodes: 4, queued: 0
Valid Nodes: 4 Unique states: 4
IsLive: true
PASSED: Model checker completed successfully
```

[Source on GitHub](https://github.com/fizzbee-io/fizzbee/tree/main/examples/references/10-03-strong-fair-action)


## Patterns that use this

- [Message Queue Pattern](/design/patterns/message-queue/)
- [Eventual Consistency Pattern](/design/patterns/eventual-consistency/)

