Smart Manufacturing

How to Calculate OEE: Availability, Performance and Quality with Worked Examples

A clear walkthrough of how to calculate OEE: the three factors, a full worked shift example, the mistakes that inflate the number, and Python that computes OEE from machine-state MQTT messages.

How to calculate OEE illustration showing availability, performance and quality bars multiplying into one overall equipment effectiveness score
Run this on your own MQTT brokerGet a private, managed MQTT broker on the Free plan and start from ready-made code samples.
Try it free Code samples No card required

Knowing how to calculate OEE correctly matters more than the number itself, because small definition choices can move the result by many points. This guide explains the three factors, works through a complete shift example, lists the mistakes that quietly inflate OEE, and shows Python that calculates it from machine-state messages published over MQTT. By the end you can compute OEE by hand and from live data, and defend every input.

What OEE Measures

Overall Equipment Effectiveness compares what a machine actually produced with what it could have produced in the time it was scheduled to run. It answers one question: of the planned production time, how much was spent making good parts at the ideal speed?

OEE combines three losses:

  • Availability captures stops: breakdowns, changeovers and waiting.
  • Performance captures speed: running slower than ideal and short stops that are not logged as downtime.
  • Quality captures defects: scrap and rework.

Multiplying the three factors gives OEE. A machine with perfect availability and quality but running at half speed has 50 percent OEE, which is exactly the signal you want.

The OEE Formula

Factor Formula Uses
Availability Run time / Planned production time Stop durations
Performance (Ideal cycle time x Total count) / Run time Count and ideal cycle time
Quality Good count / Total count Good and reject counts
OEE Availability x Performance x Quality All three

An equivalent shortcut is OEE = (Good count x Ideal cycle time) / Planned production time. It produces the same result and is a useful check on your arithmetic. The three-factor version is still worth calculating, because it tells you where the losses are.

Definitions that must be fixed before you start:

  • Planned production time is shift time minus planned stops such as breaks and planned maintenance. Whether changeovers count as planned or unplanned is a site decision; most lean practitioners treat them as availability losses so they stay visible.
  • Run time is planned production time minus all unplanned stop time.
  • Ideal cycle time is the fastest the machine can reliably make the part, usually from the equipment design or a demonstrated best rate, not the standard used for costing.
  • Total count includes good and rejected parts.

Worked Example: One Shift on a Filling Machine

Take an eight-hour shift (480 minutes) with two 15-minute breaks.

  1. Planned production time = 480 - 30 = 450 minutes.
  2. Stops during the shift: a 25-minute changeover and a 20-minute breakdown, so 45 minutes of downtime.
  3. Run time = 450 - 45 = 405 minutes.
  4. Ideal cycle time is 1.0 second per unit, so the ideal rate is 60 units per minute.
  5. Total count = 21,000 units.
  6. Rejects = 420 units, so good count = 20,580.

Now the factors:

  • Availability = 405 / 450 = 0.900 (90.0 percent)
  • Performance = (1.0 s x 21,000) / (405 x 60 s) = 21,000 / 24,300 = 0.864 (86.4 percent)
  • Quality = 20,580 / 21,000 = 0.980 (98.0 percent)
  • OEE = 0.900 x 0.864 x 0.980 = 0.762 (76.2 percent)

Check with the shortcut: (20,580 x 1.0 s) / (450 x 60 s) = 20,580 / 27,000 = 0.762. The two methods agree.

What does this tell the team? The biggest single loss is performance: in 405 minutes of running, the machine made 3,300 fewer units than it could have. That loss is made of micro-stops and reduced speed, which rarely appear in a manual log. The packaging line monitoring article shows how to break performance loss down further.

Common Mistakes When Calculating OEE

These are the errors that make OEE look better than reality or make machines impossible to compare:

  1. Using a slow ideal cycle time. If the "ideal" is the planning standard with padding, performance can exceed 100 percent or look artificially high. Use the true design or best demonstrated rate.
  2. Excluding changeovers. Calling every changeover "planned" removes a major improvement opportunity from view.
  3. Counting good parts only in performance. Performance uses total count. Using good count double-counts quality loss.
  4. Averaging OEE percentages across machines. A small machine and a large one should not have equal weight. Sum the underlying times and counts, then calculate.
  5. Counting at every station on a line. For a line, OEE should use the output of the last station and the ideal rate of the constraint.
  6. Mixing products with different cycle times. Calculate ideal time per product (count x ideal cycle time for each product) and sum it, rather than using one rate for the whole shift.

For multi-product shifts, the shortcut form handles mixes cleanly: OEE = sum over products of (good count x ideal cycle time) / planned production time.

Choosing the Ideal Cycle Time

The ideal cycle time is the input most often disputed, and it has the largest effect on performance. Three sources are common:

  • Nameplate or design rate from the equipment supplier. Honest, but sometimes unreachable for a given product.
  • Best demonstrated rate, the fastest cycle the machine has sustained for a meaningful period on that product. Practical and defensible.
  • Standard rate from costing or planning. Usually padded and therefore the wrong choice for OEE.

Pick the design rate or the best demonstrated rate, record it per product and machine, and change it only through a deliberate review. When you keep master data like this in a retained MQTT message per machine (for example a config topic on your ConnectMQ broker), every calculation service and dashboard reads the same value, and a change is visible to everyone at once.

How to Calculate OEE from MQTT Machine Data

Hand calculation is fine for a training session, but in practice OEE should come from machine signals. A typical setup publishes two kinds of messages per machine to an MQTT broker:

connectmq/demo/<your-id>/plant1/line2/filler/state   {"state": "RUNNING", "ts": 1792130400}
connectmq/demo/<your-id>/plant1/line2/filler/counts  {"total": 21000, "reject": 420, "ts": 1792159200}

State messages are published on every change; counts are cumulative for the shift and published periodically. The function below calculates OEE for a window from a list of state events and the start and end counts. It treats PLANNED_STOP as excluded from planned time and every other non-running state as downtime.

from dataclasses import dataclass


@dataclass
class StateEvent:
    ts: float      # unix seconds
    state: str     # RUNNING, DOWN, IDLE, SETUP, PLANNED_STOP


def calculate_oee(events, window_start, window_end, total_count, reject_count, ideal_cycle_s):
    """Return availability, performance, quality and OEE for one window."""
    events = sorted(events, key=lambda e: e.ts)
    planned_stop = 0.0
    run_time = 0.0

    for i, ev in enumerate(events):
        start = max(ev.ts, window_start)
        end = events[i + 1].ts if i + 1 < len(events) else window_end
        end = min(end, window_end)
        if end <= start:
            continue
        duration = end - start
        if ev.state == "PLANNED_STOP":
            planned_stop += duration
        elif ev.state == "RUNNING":
            run_time += duration

    planned_time = (window_end - window_start) - planned_stop
    if planned_time <= 0 or run_time <= 0 or total_count <= 0:
        return {"availability": 0.0, "performance": 0.0, "quality": 0.0, "oee": 0.0}

    availability = run_time / planned_time
    performance = min((ideal_cycle_s * total_count) / run_time, 1.0)
    quality = (total_count - reject_count) / total_count
    return {
        "availability": round(availability, 4),
        "performance": round(performance, 4),
        "quality": round(quality, 4),
        "oee": round(availability * performance * quality, 4),
    }


if __name__ == "__main__":
    t0 = 0
    shift = [
        StateEvent(t0, "RUNNING"),
        StateEvent(t0 + 120 * 60, "PLANNED_STOP"),   # break
        StateEvent(t0 + 135 * 60, "SETUP"),          # changeover 25 min
        StateEvent(t0 + 160 * 60, "RUNNING"),
        StateEvent(t0 + 300 * 60, "PLANNED_STOP"),   # break
        StateEvent(t0 + 315 * 60, "RUNNING"),
        StateEvent(t0 + 400 * 60, "DOWN"),           # breakdown 20 min
        StateEvent(t0 + 420 * 60, "RUNNING"),
    ]
    print(calculate_oee(shift, t0, t0 + 480 * 60, 21000, 420, 1.0))

Running it reproduces the worked example: availability 0.9, performance 0.8642, quality 0.98, OEE 0.7622. Note the min(..., 1.0) cap on performance. If you hit it regularly, the ideal cycle time is wrong; fix the master data instead of relying on the cap.

To turn this into a live number, subscribe to the state and count topics, keep the events for the current shift in memory, and recalculate every minute. The real-time OEE monitoring tutorial builds exactly that service, and the OEE vs TEEP comparison explains what changes when you measure against calendar time instead of planned time.

Trying It on a Real Broker

You can test the message flow without any hardware using the free public MQTT broker at broker.connectmq.com. Publish a state change by hand:

mosquitto_pub -h broker.connectmq.com -p 1883 -i oee-test-h4v7 -t "connectmq/demo/h4v7/plant1/line2/filler/state" -m '{"state":"RUNNING","ts":1792130400}' -r

Remember that the public area is readable by anyone. For real production data, ConnectMQ gives you a private hosted MQTT broker with credentials, TLS and a portal where you can watch the topics live. For how OEE fits with other plant metrics, see the smart manufacturing guide.

Get Started with ConnectMQ

Create a free Serverless broker at app.connectmq.com with no credit card, publish your machine states and counts, and calculate OEE from real data instead of end-of-shift estimates.

Frequently Asked Questions

What is a good OEE score?

It depends on the process and how strictly you define the inputs. Use OEE to track improvement on the same machine with fixed definitions rather than to compare against generic benchmarks.

Can performance be higher than 100 percent?

Not if the ideal cycle time is correct. A performance above 100 percent means the ideal cycle time is too slow and should be corrected.

Should changeovers count against availability?

Most improvement programs include them as availability loss so setup reduction stays visible. Whatever you choose, apply it consistently across machines and shifts.

How do I calculate OEE for a whole line?

Use the output count of the final station, the ideal rate of the constraint machine and line-level stop time. Do not average the OEE of individual machines.

Related articles

OEE vs TEEP vs OOE: Which Metric Should You Use?

OEE, OOE and TEEP share the same performance and quality factors but measure against different time bases. This comparison works through one example and lists the MQTT signals each metric needs.

7 min read

All articles →

Your private MQTT broker is a few clicks away

Create an account, get your broker credentials and connect your first device — no servers to install, patch or scale.