Test Types & Methods

What Is AOI, SPI, and AXI in PCB Manufacturing

AOI, SPI and AXI are the automated inspection steps on an SMT line. What each one catches, where it sits, and how to trend the results.

JJulien Buteau
beginner7 min readMarch 14, 2026

SPI, AOI and AXI are the three automated inspection steps on an SMT line. They look at the board rather than testing it electrically, and together they catch most assembly defects before any power is applied. This guide covers what each one sees, where it belongs in the line, and how to get more out of the data than a pass/fail count.

The Three Inspections

StepFull nameWhere it sitsWhat it sees
SPISolder Paste InspectionAfter paste printing, before placementPaste volume, area, height, offset, bridging
AOIAutomated Optical InspectionAfter reflow (often also after placement)Presence, polarity, offset, tombstoning, visible solder defects
AXIAutomated X-ray InspectionAfter reflowHidden joints: BGA, QFN, bottom-terminated parts, voiding

The order is the logic. SPI checks the process input, AOI checks what the process produced where a camera can see it, and AXI checks what a camera cannot see at all.

SPI: Solder Paste Inspection

Roughly 60-70 % of SMT defects originate at paste print. SPI is where they are cheapest to catch, because nothing has been placed yet and the board can simply be wiped and reprinted.

MeasurementTypical specWhat a drift means
Volume80-120 % of apertureStencil wear, squeegee pressure, paste viscosity
HeightWithin ±25 % of stencil thicknessStencil damage, board support
Area80-120 %Aperture clogging
Offset X/YUnder 25 % of pad widthStencil-to-board alignment
BridgingNoneExcess paste, poor gasketing

SPI is the strongest candidate on the line for statistical process control, because it produces a continuous numeric value per pad, thousands per board. A control chart on paste volume shows stencil wear days before AOI starts flagging opens.

AOI: Automated Optical Inspection

AOI compares the board against a golden image or a rules model.

Defect classDetected reliably
Missing componentYes
Wrong component (visibly different)Yes
Polarity / orientationYes, with good lighting and marking
Tombstoning, billboardingYes
Offset, rotationYes
Solder bridge (visible)Yes
Insufficient / excess solder (visible fillet)Usually
Cold joint under a part bodyNo
BGA / QFN jointsNo

AOI's weakness is a generic one: false calls. A machine tuned to catch every real defect will also stop good boards, and an operator who overrides 50 false calls an hour will eventually wave a real one through. The false-call rate is worth tracking as a number in its own right.

AXI: Automated X-ray Inspection

AXI sees through the package. It is the only inspection that reaches BGA, QFN and other bottom-terminated joints.

MeasurementWhy it matters
Void percentageThermal and mechanical reliability, typically under 25 % for BGA
Joint shape and standoffCold joints, head-in-pillow, insufficient collapse
Open jointsNot visible by any optical method
Solder volume per ballPaste and reflow consistency at the package level

AXI is slower and more expensive per board than AOI, so many lines sample rather than inspect 100 %, or apply it only to the packages that need it.

Where They Sit

Paste print → SPI → Place → Reflow → AOI → AXI → ICT/FCT

Each step is a decision point with its own yield. That is the single most useful thing to get right in the data: one procedure per inspection step, so a drop at SPI is visibly an SPI problem and not blended into a line-wide number.

Getting the Data Out of the Machines

SPI, AOI and AXI machines all produce results, usually as CSV, XML, or a database row per board. The common mistake is to keep only the verdict. A board that passed SPI at 119 % paste volume is a different board from one that passed at 101 %, and only one of them is telling you the stencil needs cleaning.

The useful pattern is a thin importer per machine: read its output, map the values onto named measurements, and upload one run per board per step.

plugs/spi_machine.py
22 lines
import csvclass SpiMachine:    """Reads the SPI machine's CSV export for one board."""    def __init__(self):        self._rows = None    def load(self, path: str):        with open(path, newline="") as fh:            self._rows = list(csv.DictReader(fh))    def volume_stats(self) -> tuple[float, float, float]:        vols = [float(r["volume_pct"]) for r in self._rows]        return min(vols), sum(vols) / len(vols), max(vols)    def offset_max(self) -> float:        return max(float(r["offset_pct"]) for r in self._rows)    def bridges(self) -> int:        return sum(1 for r in self._rows if r["bridge"] == "1")
phases/spi_import.py
def spi_import(measurements, spi_machine):    """One run per board, carrying the numbers rather than the verdict."""    spi_machine.load("/data/spi/latest.csv")    lo, mean, hi = spi_machine.volume_stats()    measurements.paste_volume_min = lo    measurements.paste_volume_mean = mean    measurements.paste_volume_max = hi    measurements.paste_offset_max = spi_machine.offset_max()    measurements.bridge_count = spi_machine.bridges()
procedure.yaml
44 lines
name: SPI Inspectionversion: 1.0.0description: Solder paste inspection results per boardunit:  serial_number:    default_value: "PCBA000001"  part_number:    default_value: "PCBA-100"plugs:  - name: spi_machine    python: plugs.spi_machine:SpiMachinemain:  - name: SPI Import    python: phases.spi_import    measurements:      - name: Paste Volume Min        unit: "%"        validators:          - operator: ">="            expected_value: 80      - name: Paste Volume Mean        unit: "%"        validators:          - operator: ">="            expected_value: 90          - operator: "<="            expected_value: 110      - name: Paste Volume Max        unit: "%"        validators:          - operator: "<="            expected_value: 120      - name: Paste Offset Max        unit: "%"        validators:          - operator: "<="            expected_value: 25      - name: Bridge Count        validators:          - operator: "=="            expected_value: 0

Run it with tofupilot run ./procedure.yaml --upload, triggered by the machine's export or a file watcher.

Record which machine and which stencil produced the board, so a drift has somewhere to point:

phases/record_context.py
def record_context(run):    run.metadata["spi_machine"] = "SPI-02"    run.metadata["stencil_id"] = "STN-4417-C"    run.metadata["line"] = "L3"

Do the same for AOI and AXI with their own procedures: component-level defect counts for AOI, void percentage and joint measurements for AXI.

What the Data Then Tells You

QuestionHow the data answers it
Is the stencil wearing?Control chart on paste volume mean, per stencil ID
Which component fails AOI most?Pareto of AOI defect types
Are BGA voids trending up?Control chart on void percentage
Is one line worse than another?Filter by the line metadata
Did the new paste lot change anything?Compare volume distributions before and after
Are our SPI limits too tight?Cpk on paste volume against the current limits

The last two are only possible because the numbers were stored. A pass/fail column cannot answer either.

Inspection Is Not Test

A board that passes SPI, AOI and AXI has been inspected, not tested. None of the three applies power or exercises a function. The electrical gates are ICT and FCT, and they catch a different class of problem entirely: a correctly-soldered board with a marginal design or a firmware fault passes all three inspections.

The complementary failure is also worth naming: a board that passes FCT can still have a 40 % BGA void that will fail in the field in eighteen months. That is precisely what AXI is for.

Common Mistakes

MistakeConsequenceFix
Storing pass/fail onlyNo SPC, no drift detection, no limit reviewStore the measured values
One blended inspection yieldA paste problem looks like a placement problemOne procedure per inspection step
Ignoring the false-call rateOperators start waving real defects throughTrack false calls as a measurement
No machine or stencil ID on the runA drift has nowhere to pointRecord them as run metadata
Treating AOI as a substitute for AXIHidden joint defects shipUse AXI for bottom-terminated packages
Treating inspection as a substitute for testFunctional and firmware faults shipKeep ICT/FCT downstream

More Guides

Put this guide into practice