What Is M Code in CNC Machine Control?
M code in a CNC machine is the class of program words that runs everything the cutting tool does not do: spindle direction, coolant, tool changes, pallet swaps, program stop and safety logic. This page explains where those codes sit in the control, how they read the machine state, and when a standard code is not enough.

In this article
- 1
- 2
- 3
- 4
- 5
- 6
- 7
What M code in a CNC machine actually controls
An M code is a miscellaneous function word. It tells the control to switch something on, off, or into a new state. G codes describe the path of the tool; M codes describe the condition of the machine while that path is being followed.
The distinction matters because the two families are executed at different moments. A G code is read ahead in the look-ahead buffer and blended into a continuous motion path. Most M code in a CNC machine is not blended. It is executed at the end of a block, once the axes have reached position, because the control cannot safely spin a spindle or release a tool while the machine is still moving.
That single design decision explains most M code behavior you will see on the shop floor. It is why a tool change stops the feed, why coolant can lag behind a rapid move, and why an operator can hear a program pause between two lines that look adjacent on the screen.
The M code in a CNC machine program does not cut metal. It makes cutting possible. Without it, the spindle never turns, the tool never changes, and chips never leave the cut.
- 1G code sets geometryCoordinates, feed rate, arc radius, cutter compensation.
- 2M code sets machine stateSpindle, coolant, tool, pallet, door, program flow.
- 3Execution timing differsMotion is blended ahead; most M code waits for in-position.
How M code in a CNC machine fits into a program
A typical milling block looks like N120 G01 X50.0 Y25.0 F800 M08. The G01 and coordinates define a linear move at 800 mm/min. The M08 turns flood coolant on. The control reads the whole block, moves the axes, then fires the M function.
Order of words inside a block is not fixed, but convention keeps M codes at the end so an operator scanning the program sees motion first and machine state second. Some controls execute M codes before motion regardless of position in the block. Read the machine manual before you rely on either behavior.
Program start and program end are the two places where M code carries the most weight. At the top, M03 or M04 starts the spindle and M08 starts coolant. At the bottom, M05 stops the spindle, M09 stops coolant, and M30 rewinds the program and resets the control for the next part.
Lines like M00 and M01 are flow control, not machine control. M00 is an unconditional stop that waits for the operator to press cycle start. M01 is an optional stop that only triggers when the optional stop switch is active. Shops use M01 between operations on the same fixture so the operator can check a feature before the next tool engages.
- 1Put M at block endKeeps motion words readable for setup staff.
- 2Check execution orderFanuc, Siemens and Heidenhain differ on block timing.
- 3Use M01 for in-process checksOptional stop keeps the program running unattended.
Common M codes and what each one does
The core set below is close to universal across ISO-style controls. Manufacturers keep these numbers because operators and post-processors expect them. Everything outside this list is where machines start to disagree.
M03 turns the spindle clockwise, M04 counterclockwise, and M05 stops it. On a mill, M03 is the normal direction for right-hand tooling. On a lathe, many shops run M04 so the tool approaches the workpiece from the top of the spindle axis.
M06 calls a tool change. The tool number usually arrives on the same line as a T word, as in T07 M06. The control may move to a safe Z height, orient the spindle, release the taper, and swap the tool. Some machines do all of that inside the macro; others need an explicit G28 or G30 before the M06 line.
M08 and M09 switch flood coolant on and off. M07 is mist. On deep pockets in aluminium, delaying M08 by even one or two blocks can raise edge temperature enough to shorten tool life and smear the surface finish.
- 1M00 / M01Program stop and optional stop.
- 2M03 / M04 / M05Spindle forward, reverse, stop.
- 3M06Tool change, usually paired with a T word.
- 4M07 / M08 / M09Mist on, flood on, coolant off.
Why execution order and machine state matter
M code in a CNC machine is stateful. M08 turns coolant on and it stays on until M09 turns it off. M03 starts the spindle and it keeps turning until M05 or another direction command arrives. Nothing resets itself between blocks.
That is why a program that runs correctly on one part can fail on the next. If a tool change macro leaves the spindle oriented and a later block assumes a free spindle, the first part may run fine and the second may alarm. State carried across operations is the most common source of intermittent M code faults.
Tool change position is a second state trap. Many controls need a machine-coordinate reference, such as G30 P2, before M06. If a program calls M06 while the Z axis sits inside the workpiece envelope, the machine either alarms out or, worse, moves through the part.
The safe pattern is explicit. Send the spindle to a known height, stop it, stop coolant, then change the tool. It costs a few seconds per tool and removes an entire class of crashes.
- 1Reset state at operationsEnd each op with M05 and M09.
- 2Move before M06Reach the tool change position in machine coordinates.
- 3Wait for in-positionDo not chain a rapid into a tool change without a stop.
When M codes differ between machine builders
The ISO list covers the basics. Beyond it, builders assign numbers freely. A pallet change might be M60 on one horizontal machining center and M80 on another. A bar feeder on a lathe could be M10, M11, or a macro call under M98.
This is why a post-processor is machine specific. The same CAM file can produce correct toolpaths and a wrong M code set if the post was written for a different builder. The geometry will be right and the machine will still refuse to run.
Some builders implement features as macro M codes rather than fixed numbers. On a Fanuc-style control, M codes above a set limit are often routed to subprograms such as O9010 through O9019. That means the function is defined by ladder logic and a macro, not by the control firmware.
If a machine arrives without a clear M code list, the fastest route is the ladder diagram and the builder's parameter manual. The operator panel rarely tells the whole story.
- 1Pallet and bar feederBuilder assigned, often M60 or above.
- 2Probe and laser toolsUsually macro driven, not fixed numbers.
- 3Get the ladder diagramIt defines what each macro M code triggers.
Practical tuning: coolant, spindle and tool change timing
Coolant timing is the easiest place to lose tool life. For deep pockets in 6061 or 7075 aluminium, turn M08 on one block before the tool enters the material so the flow is established. For a shallow facing pass, delaying M08 to the cut block saves coolant and mist in the enclosure.
Spindle ramp is the second lever. M03 starts the spindle, but the control needs time to reach commanded speed. If the following block begins a cut, add a dwell or a G04 P200 to let the spindle stabilize. In stainless 316L and 17-4PH, an unstable spindle at entry shows up as chatter marks on the first few millimeters.
Tool change time is usually the largest non-cutting cost in a short-cycle job. Grouping tools by operation and using M98 subprograms for repeated features keeps the number of M06 calls down. On a 10,000-part run, saving four seconds per part is a real number.
None of this requires exotic code. It requires reading the machine state at each block boundary and deciding whether the next block can safely start.
- 1Lead coolant by one blockEspecially in deep pockets and gummy alloys.
- 2Dwell after M03G04 P200 until the spindle reaches speed.
- 3Cut M06 countGroup tools and use M98 for repeated features.
Standard M codes and typical use
Values follow common ISO-style controls. Confirm exact behavior in the machine manual before editing a post.
| Code | Function | Typical use |
|---|---|---|
| M00 | Program stop | Operator intervention mid-cycle |
| M01 | Optional stop | First-article check between tools |
| M03 | Spindle clockwise | Right-hand milling tools |
| M04 | Spindle counterclockwise | Lathe work from top axis |
| M05 | Spindle stop | End of each cutting operation |
| M06 | Tool change | Next tool in the sequence |
| M08 | Flood coolant on | Deep pockets, stainless, steel |
| M09 | Coolant off | Before measuring or probing |
| M30 | Program end and rewind | Last block of the main program |
| M98 / M99 | Subprogram call and return | Repeated hole patterns, family parts |
The verdict on M code
If your program only runs standard spindle, coolant and tool change logic, the ISO M code list is enough and a generic post will work. If the machine has pallet changers, bar feeders, probes or builder macros, get the ladder diagram and write a machine-specific post. Guessing a number costs more than the post ever will.
M code questions engineers ask
Can M codes be customized for a specific project?
Yes, but the customization lives in the machine, not in the part program. Builders expose macro M codes that call subprograms, and those subprograms are editable. A shop can define a code that runs a probe cycle, a pallet swap, or a custom coolant sequence.
The limit is portability. A custom M code on one machine will not run on another unless the same macro is loaded. Keep custom codes documented and keep the standard codes standard.
What happens if an M code is wrong?
The control either rejects the block with an alarm or executes something unexpected. A missing M05 before a tool change can leave the spindle turning during the swap. A wrong coolant code can flood a machine set up for mist.
Most faults show up as an alarm and a stopped machine, which is the safe outcome. The dangerous case is a valid but wrong code that moves an axis or releases a clamp at the wrong moment.
Do all CNC machines use the same M code standard?
The core set is close to universal. M03, M05, M06, M08, M09 and M30 behave the same on most mills and lathes.
Above that core the numbers diverge. Pallet changers, bar feeders, chip conveyors and probes are builder specific. Treat any M code outside the standard list as machine documentation, not general knowledge.
How does M code affect surface finish?
Indirectly but clearly. Coolant timing, spindle ramp and tool change position all sit in M code. Get them wrong and the tool enters the cut hot, slow or off position.
On aluminium and stainless work we hold Ra 0.8–1.6 μm on milled faces, and Ra 0.2–0.8 μm where a finishing pass is specified. Those numbers depend on the cutting parameters, and the M code sequence decides whether those parameters are reached before the cut starts.
Should M codes go at the start or end of a block?
Put them at the end by convention, so the motion words stay readable. But check the control manual, because execution order is not guaranteed to follow word order.
Some controls fire M functions before motion in the same block. Others wait for in-position. The difference matters most for coolant and for anything that moves a clamp.
How is M code accuracy checked in production?
By running the program in single block and dry run before the first part, then verifying the first article against the drawing. Machine state is reset at each operation so a later tool cannot inherit a stale condition.
For production runs we keep the approved program revision locked. Edits go through a change record, and the first part after any edit is inspected. That is how a 99.99% qualification rate is held on repeating work.
Send us your part and your control
We machine from one prototype to 10,000+ part runs, with quotation and free DFM analysis within 12 hours. Tell us the control on your machine and we will match the M code sequence to it.
12-hour quote100% inspectionNo minimum order quantity