SAP transport management: STMS, transport routes, and a clean import strategy
How the SAP transport system really works — the transport domain and STMS, Workbench vs Customizing requests, consolidation and delivery routes, import strategy and return codes, SCC1 and CTS+, and the mistakes that break production.
Every change that reaches a production ABAP system — a corrected program, a new customizing entry, a fresh data dictionary object — got there through the Change and Transport System. Get transport management right and change flows predictably from development to production, in order, with a record of who moved what. Get it wrong and production ends up with half a change, an object that regressed because an older request landed after a newer one, or a customizing table that is populated in one client and empty in the next. This is a practitioner's walk through STMS, transport routes, request types and a clean import strategy — with the real transactions and the real hazards.
The transport landscape and the domain
The canonical layout is three systems: development (DEV), quality assurance (QAS) and production (PRD). Changes are made in DEV, validated in QAS, and go live in PRD — and they only ever move in that direction. Those systems are grouped into a single transport domain: one shared administrative unit with a common configuration and, on classic installations, a shared transport directory (/usr/sap/trans) holding the data files, cofiles and logs.
One system in the domain is the domain controller. It holds the reference configuration for the whole TMS, distributes it to the other systems (each of which runs the TMSADM RFC user), and is where you edit routes. In practice the domain controller lives on the most stable system — often PRD or a dedicated Solution Manager — because every other member depends on it being reachable. STMS is the cockpit: the transaction where you see the domain, the systems, the routes, and every import queue.
Requests and tasks: Workbench vs Customizing
Work is recorded in transport requests, and a request contains tasks — normally one task per developer. Objects and their locks are recorded against a task; you release the tasks first, then release the request, and only a released request produces the files that can be imported elsewhere. The person who owns the request owns the release; the people who own the tasks own their piece of it. Releasing is done in the Transport Organizer — SE09 (the workbench view), SE10 (the customizing view) and SE01 (the extended view) are three faces of the same tool.
There are two request types, and confusing them is one of the most common sources of "it worked in QAS but not in PRD":
| Aspect | Workbench request | Customizing request |
|---|---|---|
| What it carries | Repository / DDIC objects — programs, function modules, classes, tables, domains, screens | Client-specific configuration — IMG settings, control tables, number ranges |
| Client dependency | Cross-client — the objects are the same in every client | Client-specific — data lands in the target client the route imports into |
| Transport layer | Derived from the object's package (development class) | The standard transport layer of the source client |
| Typical trigger | A change to code or the data dictionary in SE80/SE38/SE11 | An entry made in SPRO / an IMG activity |
The subtlety worth internalising: cross-client customizing (client-independent tables) is still recorded in a Customizing request, but a change to it affects every client on the system — so a "harmless" configuration change made in a sandbox client can alter behaviour everywhere. Repository objects, by contrast, never belong in a Customizing request; if a developer parks a program change there it may not transport with the transport layer you expect.
Transport routes and layers
Routes decide where a released request can go. There are two kinds:
- Consolidation route — from an integration system (DEV) to a consolidation system (QAS). A request is released into this route; its target buffer is QAS. A consolidation route is bound to a transport layer, and a package's transport layer is what decides which consolidation route its objects follow. Your own developments typically sit on a
Zlayer (e.g.ZDEV); SAP-owned objects sit on theSAPlayer. - Delivery route — from a consolidation system (QAS) onward to one or more delivery systems (PRD). Requests are forwarded along delivery routes automatically once they are imported into the consolidation system, so what you approved in QAS is what queues up for PRD.
Each system has an import queue — the ordered list of released requests waiting to be imported into it — which you open with STMS_IMPORT (or by drilling into the system from the STMS import overview). The queue order is the import order, and that order is the whole game.
A clean import strategy
When you import, you choose the scope:
- Import all — process the entire queue in buffer order. This preserves the sequence in which requests were released, which is exactly why it is the safe default for a periodic import window.
- Import single / selective — import one request (or a chosen set) ahead of the rest. Convenient, and the most reliable way to create an out-of-order accident: you pull request 9 forward, it depends on an object last changed in request 7 which is still sitting behind it, and PRD ends up with the older version.
Under the hood, tp (the transport control program) orchestrates the import and calls R3trans to move the actual objects; the background dispatcher job RDDIMPDP (event-triggered per client) runs the import steps — dictionary import, activation, main import and the after-import methods / XPRA reports. You do not call these by hand from STMS, but knowing they exist explains why a stuck import is often a stopped RDDIMPDP or an event that never fired.
Every import step reports a return code, and reading them correctly is the difference between "done" and "looks done":
| RC | Meaning | What to do |
|---|---|---|
| 0 | Imported successfully, no issues | Nothing — this is the target |
| 4 | Imported with warnings — e.g. a repair, a generation warning, an object not activated | Read the log; 4 is normal but must be understood, not assumed benign |
| 8 | Errors — not everything imported (activation failed, syntax error, missing dependency) | Investigate before the next import; the target is now partially changed |
| 12 | Fatal — the import was cancelled (system/tp/R3trans problem) | Stop; resolve the underlying failure before retrying the queue |
A blanket rule of thumb — "only 0 and 4 are acceptable" — is a good gate, but 4 still earns a look at the log. For customizing that must land in a specific client the transport did not target, use SCC1 to copy the change between clients on the same system after the import; the transport moves client-specific data into the route's target client only, and SCC1 is how you propagate it to the others without re-transporting. Finally, non-ABAP content — Java, portal, PI/ESR objects — moves through CTS+ (enhanced CTS), which layers the same transport infrastructure and STMS routes over deployable non-ABAP artefacts, so a mixed landscape can still enforce one change path.
Common pitfalls
- Importing to PRD out of sequence. Selective imports that ignore buffer order are the classic way a newer object gets overwritten by an older request that was imported after it. Prefer "import all" into PRD.
- A task that was never released. If the request is released but a task inside it is not, the objects locked in that task never make it into the files — the import "succeeds" and the change is silently missing.
- Transport of copies vs a released request. A transport of copies (TOC) moves a snapshot for testing but does not record the objects against their originals and does not travel the normal consolidation path — it is not a substitute for releasing the real request through DEV → QAS → PRD.
- Mixing request types. Repository changes in a Customizing request, or client-specific config assumed to be cross-client, produce imports that land in the wrong scope or follow the wrong transport layer.
- Cross-client customizing surprises. A change to a client-independent table made in any client affects all clients on that system — including ones you did not mean to touch.
What good looks like
- Keep the flow one-directional: change in DEV, validate in QAS, import to PRD — never sideways, never backwards.
- Release tasks and the request; confirm the request left the buffer with objects attached before you rely on it.
- Import PRD with "import all" on a scheduled window so buffer order is preserved.
- Read every return code — treat 8 and 12 as stop conditions and never wave through a 4 without checking the log.
- Use
SCC1deliberately for customizing that must reach clients the route did not target. - Keep transport types honest: real changes go through released requests, not transports of copies.
- Retain the import history — who imported which request, into which system, when, with what return code — as an auditable record.
How Farrenio fits
The last checklist item is the one that quietly decays: the import history lives in each system's STMS logs, and nobody correlates it across the landscape until an audit or an incident forces the question "how did that get into PRD?". Farrenio surfaces and audits transport imports across every monitored system as one attributed record — which request was imported into which SID, by whom, at what time, and with which return code — so an out-of-sequence import or a request that landed with an 8 is visible where you are already watching the estate, not buried in a per-system log you have to go hunting for. That sits alongside the rest of the signals on the SAP Basis monitoring page, and complements the guided, role-scoped operations described under SAP Basis automation.
If you want to see transport imports tracked and attributed across your own landscape, write to contact@farrenio.com.
Run Farrenio against your own SIDs.
14-day sandbox tenant. No card. Real data.
Read next
All posts
SAP BasisSAP kernel patching: a practical guide
What a SAP kernel patch involves, how a rolling kernel switch keeps downtime low, how to validate it, and why tracking kernel, patch and DBSL levels across the landscape matters more than any single patch.
SAP BasisSAP system refresh and client copy with SCC5 and SCCL
System copy vs client copy vs targeted refresh — which one a request really needs, the SCCL copy profiles, deleting a client with SCC5 safely, why BDLS is the step everyone forgets, and what can be automated today.
SAP BasisA web-based alternative to SM50, SM37 and ST22
Why operating SAP through SAPGUI gets expensive across many SIDs, what a web-native alternative covers, and what to look for in one.