If you search for "transport management in SAP," you get two completely different answers mixed together, and only one of them is about the tool this article covers.
SAP Transportation Management (SAP TM) is a logistics application: freight orders, carrier selection, route planning, freight settlement. The SAP Transport Management System (TMS, usually called STMS after its transaction code) is a Basis tool that moves software changes and configuration from one SAP system to another. They share three letters and nothing else. This guide is about the second one.
The Transport Management System is how a change you make in development reaches production. It models your system landscape, defines the path changes travel along, maintains an import queue for every target system, and records what was imported, when, by whom, and whether it worked. Get it right and releases are boring. Get it wrong and you find out in production.
The vocabulary, in the order you need it
Four concepts do most of the work, and they nest inside each other.
Transport domain. All the SAP systems administered together by one TMS configuration. Typically this is your whole landscape — development, quality assurance, production, plus any sandbox or training systems.
Domain controller. One system in the domain holds the master configuration and distributes it to every other system. Convention is to use the development system, because it is the one that exists first and is the least likely to be rebuilt. Configuration changes are made on the controller and pushed out; making them anywhere else does not work.
Transport route. The path a change takes. A *consolidation* route moves changes from development to the next system (usually QA). A *delivery* route moves them onward (QA to production). A change does not skip a system on the route unless someone deliberately makes it skip.
Transport layer. The mechanism that decides *which* route a given development package uses. Every package is assigned a transport layer, and every transport layer maps to a route. In a single-track landscape there is one customer layer and this is invisible. The moment you have two development streams — a project track and a maintenance track — layers are what keep them apart.
The practical consequence: if a developer's changes are landing in the wrong system, the answer is almost always the transport layer assigned to their package, not the route.
Request types, and the one that causes incidents
A transport request is a container. What it can hold depends on its type, and the distinction matters more than most teams realise.
| Request type | Carries | Client scope |
|---|---|---|
| Workbench request | ABAP repository objects — programs, function modules, classes, dictionary objects, Fiori artifacts | Cross-client |
| Customizing request | Configuration table entries | Client-specific |
| Transport of Copies | A snapshot of chosen objects, sent to one target | Does not change object ownership |
| Relocation | Moves development ownership of objects between systems | Rarely needed, easy to misuse |
The recurring incident: a functional consultant makes a Customizing change in the development client, tests it in that same client, and it works. It is captured in a Customizing request. But a related setting was made in a different client, or in a cross-client Customizing table, and only part of the change travels. In QA, the configuration is half-present, and the behaviour differs from development in a way nobody can immediately explain.
The second recurring incident is the reverse: a change is made directly in a client that has no transport recording enabled, so nothing is captured at all. It works in development permanently, and never appears anywhere else.
Neither is a TMS defect. Both are the system doing exactly what it was configured to do.
What actually happens during an import
Understanding the import steps is what separates "the transport failed" from "the transport failed at DDIC activation, which means a dictionary object it depends on isn't there yet."
An import is not atomic. It runs as a sequence:
- Dictionary import — the ABAP Dictionary definitions in the request are brought in.
- Dictionary activation — those definitions are activated, which may mean table conversions. This is where a structure change on a large table turns a two-minute import into a two-hour one.
- Main import — the remaining repository objects and table entries are imported.
- After-import methods and XPRA — programs that run after the import to fix up data or trigger follow-on activity.
- Generation — ABAP loads are regenerated.
A request can pass step 3 and fail step 4. The objects are in the system; the follow-up work is not. This is why "the import finished" and "the change is working" are different statements.
The programs doing the work are tp, the transport control program, and R3trans beneath it. TMS is the layer that decides what tp is asked to do and records the result.
Reading the return code
Return codes are the single most useful diagnostic and the most commonly misread. SAP's own definitions:
| Return code | Meaning |
|---|---|
| 0 | Transport ran without errors. |
| 4 | Warnings were issued. All objects transported successfully, but something happened that may not have been intentional — for example, the request contained an object deletion. Read the warnings. |
| 8 | Individual objects could not be transported successfully. You must analyze and correct the errors. Typical causes: an original object was not overwritten, or a repaired object was not overwritten. |
| 12 or higher | A critical error, probably not caused by the contents of the request. Escalate to the system administrator. |
Two things worth knowing that are not obvious from the table. First, individual transport steps produce return codes from the set 0, 4, 6, 8, 12, 13, 14, 16 — the combined code you see is normally the maximum of those. Second, a general error, such as tp being unable to reach the database, produces a code above 200, and in that case the combined return code is the general error rather than the step maximum. A three-digit return code is a different class of problem from an 8.
Every return code has a detailed long text attached. Reading it takes ten seconds and is skipped constantly. tp also has an explainrc command that prints the short description for a code.
The habit worth building: treat return code 4 as something to read rather than something to acknowledge. Most production surprises that get traced back to a transport were visible as a warning at import time.
The transport directory
Every system in a transport group shares one directory, by default /usr/sap/trans. Its contents are worth knowing because a surprising share of transport problems are filesystem problems.
- `data/` — the actual object data, as
R<number>.<SID> - `cofiles/` — control files describing each request's steps and status, as
K<number>.<SID> - `buffer/` — the import queue for each system
- `log/` — import and export logs
- `bin/` —
TP_DOMAIN_<SID>.PFL, the transport profile - `tmp/`, `sapnames/`, `actlog/`, `EPS/` — working files, object locks by user, action logs, and packages
A transport request is really a matched pair: the data file and the cofile. Lose the cofile and the request cannot be imported even though its contents are intact. This is why "let me just copy the R file over" does not work, and why the transport directory belongs in your backup scope even though it holds no business data.
If systems in a domain cannot see the same directory with the same permissions — a common outcome after a system refresh, or when a landscape spans operating systems — transports fail in ways whose error messages point nowhere useful.
The transactions you will actually use
| Transaction | What it is for |
|---|---|
STMS | The TMS itself — configuration, routes, import overview |
STMS_IMPORT | The import queue for a specific system |
STMS_QA | Approval step, where QA gating is configured |
SE01 | Transport Organizer, extended view — the one to learn |
SE09 / SE10 | Workbench and Customizing Organizer |
SE03 | Transport Organizer tools: find objects in requests, unlock objects |
SCC1 | Copy a request between clients in the same system |
SE03 deserves a note. "Search for Objects in Requests" answers the question "which request contains this program, and has it been transported?" — which comes up during every incident investigation and is faster than any alternative.
Unconditional modes: the loaded gun
tp accepts unconditional modes that override its safety checks — ignoring that a request was already imported, overwriting originals, and similar. They exist because occasionally you genuinely need them.
They are also the standard workaround when an import fails and someone is under time pressure, and that is where landscapes get damaged. Overwriting an original object in the wrong direction can silently discard work. Re-importing a request that was already imported can reintroduce a state someone deliberately moved past.
The rule worth enforcing: unconditional modes require a named reason and a second person, and the reason goes in the change record. If your team uses them routinely, the underlying problem is the transport process, not the safety check.
Where landscapes go wrong
A handful of failure patterns account for most of the transport incidents we see.
Imports out of sequence. Requests are numbered in export order for a reason. Importing selectively, or letting a queue be cherry-picked under deadline pressure, produces a target system that is not a state any development system was ever in. Import the queue in order, or accept that you are now debugging a landscape nobody has tested.
Overtakers. A later request imported before an earlier one that touches the same objects. The later change is then silently reverted when the earlier one arrives. This is the mechanism behind "we fixed that bug twice."
Transport of Copies used as process. Fine for a one-off — sending a fix to a test system for validation. Used routinely, it decouples what is in production from what is in the transport history, and eventually nobody can reconstruct how production reached its current state.
No QA gate. STMS_QA exists so that imports into production require approval. Landscapes without it rely entirely on people not making mistakes at 6pm on a Friday.
Stale import buffers. After a system copy or refresh, the target's buffer can contain requests that no longer make sense. Cleaning this up is part of a refresh runbook; skipping it produces failures weeks later that look unrelated.
Beyond ABAP
Two extensions are worth knowing exist:
CTS+ (Enhanced Change and Transport System) lets the same transport mechanism carry non-ABAP objects — Java, portal content, and other artifacts — so a landscape has one change pipeline instead of several.
gCTS (git-enabled CTS) stores ABAP changes in a Git repository, bringing branching and pull-request-style review to ABAP development. It is a genuine shift in how transports are managed rather than a wrapper, and it is worth evaluating if your development organisation already works this way in other stacks.
Neither replaces understanding the classic model, because the classic model is what is running in almost every landscape today.
What good looks like
A transport process that does not generate incidents tends to have the same characteristics:
- Requests are released by the developer who owns them, not batch-released by an administrator at the end of a sprint
- Import queues are imported completely and in order, on a schedule, not selectively on request
- Return code 4 is read, not acknowledged
- Unconditional modes require justification
- Production imports pass through an approval step
- The transport directory is monitored for free space and included in backups
- After every system refresh, the buffer and TMS configuration are checked before the first import
None of this is difficult. It is, however, the kind of discipline that only gets built after an incident, unless someone deliberately builds it first.
If you would rather not learn these lessons from your own production system, this is the sort of thing an experienced Basis team does as a matter of routine — our managed Basis services cover transport operations, landscape configuration, and the release discipline around them. For a one-off review of an existing landscape, Basis consulting is the better fit.
Related reading
- SAP Transport Tables: E070, E071 and the Rest — how to query transport data directly
- SAP Transport Errors and Return Codes — diagnosing failed imports
- What Is SAP Basis? — where transports sit in the wider Basis discipline