Ask what pdflatex is and the accurate answer is not “a program.” It is the pdfTeX engine started with the LaTeX format preloaded. Lined up as command names, pdflatex, lualatex and platex look like separate pieces of software; in reality each is a combination of two independent axes — an engine (the program that runs) and a format (a body of macros compiled in advance). Once you can see those axes, several things explain themselves at once: what a .fmt file is, why running latex gives you a DVI rather than a PDF, and what actually became of LaTeX3.
The difference between an engine and a format
An engine is an executable; a format is data. The engine is the program that reads a .tex file and typesets it — tex, pdftex, xetex, luahbtex, euptex and so on. A format is a large collection of macros such as \documentclass and \section, expanded ahead of time and frozen into a single dump: a .fmt file. The engine loads that .fmt in an instant at start-up, so it never has to redefine tens of thousands of lines of macros on each run.
So “LaTeX” is the name of a format, not of an engine. The same LaTeX format can be run on different engines, and the command you type names a particular engine-plus-format pair. You do not have to guess at that mapping: it exists as a single configuration file inside TeX Live called fmtutil.cnf. Its four columns are format name, engine, hyphenation-pattern file and arguments, and the TeX Live 2024 copy holds 54 lines — 54 registered combinations.
$ grep -E '^(tex|latex|pdflatex|lualatex|xelatex|uplatex|amstex|pdfcsplain) ' \
$(kpsewhich fmtutil.cnf)
# format engine hyphenation arguments
tex tex - tex.ini
latex pdftex language.dat *latex.ini
pdflatex pdftex language.dat *pdflatex.ini
xelatex xetex language.dat -etex xelatex.ini
lualatex luahbtex language.dat,language.dat.lua lualatex.ini
uplatex euptex language.dat *uplatex.ini
amstex pdftex - *amstex.ini
pdfcsplain luatex - csplain.ini
pdfcsplain pdftex - csplain-utf8.ini
pdfcsplain xetex - csplain.iniTwo things follow from that table. First, one format name can appear against several engines — pdfcsplain has three rows, for luatex, pdftex and xetex. There is no better proof that format and engine are orthogonal. Second, the * prefixed to the arguments: it instructs the engine to dump with the e-TeX extensions enabled, and the file’s own header comment explains that this is essentially equivalent to the -etex option. The latex row has the *; Knuth’s tex row does not. Modern LaTeX’s dependence on e-TeX is compressed into that one character.
What is actually inside a .fmt file
It is a memory dump of the engine’s entire internal state. Not source code, not text. Macro definitions, category codes, hyphenation patterns, maths font assignments — whatever is in the engine’s memory the moment it finishes reading latex.ltx is written straight out as binary. In TeX Live 2024, latex.fmt is about 8.2 MB. The difference between re-reading those 8.2 MB and re-interpreting latex.ltx from scratch every time is exactly why LaTeX starts instantly.
There is one place where the relationship between engine and format is visible in the file system itself: a .fmt is stored not under the format’s name but in a directory named after the engine. Under texmf-var/web2c/ in TeX Live 2024 you find directories tex/, pdftex/, xetex/, luahbtex/, euptex/, each holding the formats dumped by that engine. tex/tex.fmt is plain TeX, pdftex/latex.fmt is LaTeX, euptex/uplatex.fmt is upLaTeX — same .fmt extension, but a different object depending on which engine built it.
# Formats are filed by ENGINE, not by format name.
$ ls /usr/local/texlive/2024/texmf-var/web2c/
aleph euptex hitex luahbtex luajittex luatex metafont pdftex tex xetex
$ ls /usr/local/texlive/2024/texmf-var/web2c/euptex/
eptex.fmt euptex.fmt platex.fmt ptex.fmt uplatex.fmt ...
# Ask kpathsea which .fmt a given engine would load.
$ kpsewhich -engine pdftex latex.fmt
/usr/local/texlive/2024/texmf-var/web2c/pdftex/latex.fmt
$ ls -l $(kpsewhich -engine pdftex latex.fmt)
-rw-r--r-- 1 root wheel 8221690 May 4 2024 .../pdftex/latex.fmtThe mechanism on the producing side is just as simple. Start an engine with -ini and it enters an initialisation mode in which no .fmt is loaded. Feed it a source such as latex.ltx in that state and finish with the primitive \dump, and the internal state at that moment is written out as a .fmt. initex, once a separate executable, is nothing but a name for this -ini start-up, and now survives merely as a symbolic link to tex.
Rebuilding a format with fmtutil
The command that rebuilds a .fmt is fmtutil. It reads fmtutil.cnf and re-dumps each format using the engine and arguments listed there. It normally runs automatically when the distribution is updated, so you seldom invoke it by hand — but when you have replaced a kernel file or a hyphenation pattern and nothing changes, a stale format is usually the reason. The two forms you will actually use are fmtutil-sys --all (rebuild everything) and fmtutil-sys --byfmt latex (rebuild one).
# Rebuild one format (writes into the system tree; needs write permission).
$ fmtutil-sys --byfmt latex
# Rebuild every format listed in fmtutil.cnf.
$ fmtutil-sys --all
# Rebuild only the formats that use a given engine.
$ fmtutil-sys --byengine luahbtex
# Personal tree instead of the system tree (no root needed).
$ fmtutil-user --byfmt pdflatex
# Where did the format end up, and when was it built?
$ kpsewhich -engine pdftex latex.fmtThe difference between -sys and -user is where the result is written: the system tree (TEXMFSYSVAR) or the per-user tree (TEXMFVAR). With administrator rights, -sys is the straightforward choice; -user is for replacing only your own copy on a shared machine. Mixing the two is a reliable way to produce “but I fixed it and nothing changed”, so pick one and keep the project on it. Note also that fmtutil.cnf itself is under the distribution’s control — its opening comment states plainly that manual edits to it will be lost on update. To change something permanently, use the provided route, such as fmtutil-sys --enablefmt.
LaTeX2e: the format actually running on your machine
Today “LaTeX” means, almost without exception, LaTeX2e. It is the current version of the LaTeX macros written by Leslie Lamport, it arrived in 1994, and it is now maintained by the LaTeX Project. The “2e” signalled a small revision of the earlier LaTeX 2.09 — at the time, an interim step towards the long-planned LaTeX3. You can check which format you actually have: the kernel file latex.ltx declares \def\fmtname{LaTeX2e}, and in the copy shipped with TeX Live 2024 \fmtversion is 2023-11-01 with \patch@level 1.
The kernel is now updated on a regular cadence of about two releases a year. Memorising “the latest version” as a number is pointless — it goes stale within months. Instead, get into the habit of reading \fmtversion from latex.ltx in your own installation: that is the date of the kernel actually dumped there. For anyone who wants to try the next release early, TeX Live ships development formats alongside the stable ones. fmtutil.cnf carries rows for latex-dev, pdflatex-dev, xelatex-dev, lualatex-dev and uplatex-dev, so pdflatex-dev main.tex typesets with the forthcoming kernel. It is for compatibility-testing classes and packages, not for production manuscripts.
What actually became of LaTeX3: the answer is expl3
A LaTeX3 format never shipped. What shipped was LaTeX3’s programming language. That layer, called expl3 (the L3 programming layer), arrived not as a separate new kernel but absorbed into the inside of LaTeX2e. So the question “should I migrate to LaTeX3?” has no answer — not because there is nowhere to migrate, but because you are already using it.
The turning point is on the record. LaTeX News 31 (2 February 2020) noted that expl3 had moved over the previous decade from largely experimental to broadly stable, and reported that in that release the team adjusted the kernel to pre-load a significant portion of expl3 when the format is built. The motive was speed: documents that load fontspec under XeLaTeX or LuaLaTeX were paying a heavy cost to read Unicode data on every run.
expl3 is now part of the format. Read the kernel file latex.ltx and you can watch the logic: if expl3 is already present it announces Skipping: expl3 code already part of the format and moves on; if not it pulls it in with \input expl3.ltx; and if expl3.ltx cannot be found at all it stops with \errmessage{LaTeX requires expl3}. In other words expl3 is no longer an optional package but a required component of LaTeX2e. Writing \RequirePackage{expl3} in a document or package is still recommended for the sake of people on older formats, but on a current one it effectively does nothing. The syntax of expl3 itself — \ExplSyntaxOn, \cs_new:Npn, the typed variables of l3kernel — has a page of its own.
Formats other than LaTeX
LaTeX is the most widely used format, but not the only one. Of the 54 rows in fmtutil.cnf only a handful are LaTeX; the rest are other macro systems. amstex is worth a word here. As an executable, amstex is merely a symbolic link to pdftex, and the line amstex pdftex - *amstex.ini in fmtutil.cnf specifies the pdfTeX engine loaded with the AMS-TeX macros. AMS-TeX is the American Mathematical Society’s macro package for mathematical typesetting, built on plain TeX, and for LaTeX users it has in effect been replaced by the amsmath package. There is little reason to start a new document in AMS-TeX.
| Format | Engine that dumps it | What it is |
|---|---|---|
tex | tex | Knuth’s plain TeX — the only format without the e-TeX extensions |
latex | pdftex | LaTeX2e run by pdfTeX in DVI mode; emits a .dvi |
pdflatex | pdftex | The same LaTeX2e writing PDF directly; the de facto default for Western text |
xelatex | xetex | LaTeX2e on the XeTeX engine; system fonts and Unicode |
lualatex | luahbtex | LaTeX2e on LuaHBTeX; Lua scripting and HarfBuzz shaping available |
platex / uplatex | euptex | LaTeX2e for Japanese typesetting; emits DVI, converted to PDF by dvipdfmx |
amstex | pdftex | AMS-TeX, mathematical macros over plain TeX; superseded by amsmath for LaTeX users |
cont-en | pdftex / xetex | ConTeXt (MkII), a complete format independent of LaTeX; registered against two engines |
csplain | pdftex | A plain TeX derivative for Czech and Slovak; built with an explicit -etex |
pLaTeX and upLaTeX: the LaTeX format for Japanese
pLaTeX and upLaTeX put the LaTeX format on engines built for Japanese typesetting. Vertical writing, ruby (furigana) and Japanese line composition are handled by the pTeX family of engines, originally extended at ASCII Corporation. In TeX Live 2024’s fmtutil.cnf, both platex and uplatex are registered against the euptex engine; what separates them is the format’s initialisation file (*platex.ini versus *uplatex.ini). The difference is therefore not the executable but how the format handles characters: platex preserves traditional pTeX-compatible behaviour, while uplatex assumes Unicode internally. For a new Japanese document, uplatex is the standard choice.
This family always emits DVI, and the Japanese-bearing DVI is converted to PDF with dvipdfmx — a two-step pipeline (uplatex file.tex, then dvipdfmx file.dvi). Pair it with upmendex for the index. For document classes, Haruhiko Okumura’s jsarticle and jsbook (for pLaTeX) and their Unicode counterparts such as ujarticle are common, as is the more recent jlreq, which follows the JIS X 4051 requirements for Japanese typesetting. The internals of the engines — JFM metrics, kinsoku line-breaking rules, the implementation of vertical writing — belong to the “pTeX family” page.
Which command means which pairing
Even with the same LaTeX format, the command name settles the engine behind it, the output format and how fonts work. Read the table below from the command name outwards, left to right. In practice the rightmost column matters most: whether fontspec is available maps directly onto the choice of engine.
| Command | Engine | Output | Unicode / system fonts |
|---|---|---|---|
latex | pdfTeX in DVI mode | DVI — needs a separate conversion step | No; relies on inputenc and friends |
pdflatex | pdfTeX | PDF directly | No; relies on inputenc and friends |
platex | e-upTeX with pLaTeX-compatible settings | DVI, then dvipdfmx | Japanese through the traditional font setup |
uplatex | e-upTeX | DVI, then dvipdfmx | Unicode internally; Japanese fonts still set up the traditional way |
lualatex | LuaHBTeX | PDF directly | Yes — fontspec and luatexja |
xelatex | XeTeX | PDF, internally by way of xdvipdfmx | Yes — fontspec |
# Engines that write PDF finish in one step.
$ pdflatex main.tex # -> main.pdf
$ lualatex main.tex # -> main.pdf
$ xelatex main.tex # -> main.pdf
# DVI-based routes add a conversion step.
$ latex main.tex # -> main.dvi (pdfTeX in DVI mode)
$ uplatex main.tex # -> main.dvi (Japanese)
$ dvipdfmx main.dvi # -> main.pdfRead the first line of the log, then pin the pairing down
The first line of the log names both the engine and the format. Take This is pdfTeX, Version 3.141592653-2.6-1.40.26 (TeX Live 2024) (preloaded format=latex) apart: the first half is the engine and its version, and (preloaded format=...) is the format that was loaded. This is LuaHBTeX ..., This is XeTeX ... and This is e-upTeX ... read the same way. When collaborators report “same command, different output”, comparing this one line immediately separates an editor-configuration problem from a difference in TeX Live year or format.
And once the pairing is settled, write it down in the project and freeze it. For a thesis, as soon as the title page, table of contents, figures, tables and bibliography all build, record the command in the README or in .latexmkrc. Moving a document from lualatex to uplatex halfway through changes font selection, Japanese handling, the route to PDF and often the bibliography processing, all at once. If you must switch, verify every feature on a small trial file before going back to the real manuscript. The criteria for choosing in the first place — speed, package compatibility, the Japanese situation — are gathered on the “Choosing an engine” page.