skip to content

In Appium, does one server per session on its own --port remove the per-session port collisions?

level: seniorimportance: should knowfreq 38%

answer

  1. two different questions, one word
  2. front door versus device channel
  3. separate processes, same capability values
  4. isolation buys logs, not uniqueness

basics

~10 s

No. Separate servers only separate the HTTP front doors. Every driver still defaults to the same device-side ports, appium:systemPort on Android and appium:wdaLocalPort on Apple platforms, so those capabilities must still differ per session.

solid answer

~40 s

Running one Appium server per session, each with its own `--port` and `--base-path`, solves a different problem from the one people expect. It separates the URLs clients connect to, gives each lane its own process and its own log, and keeps a crashed or restarted server from taking the whole fleet with it. What it does not do is change the capabilities. Each server process starts a driver that still uses the supplied `appium:systemPort` on Android and `appium:wdaLocalPort` on Apple platforms, so two sessions left at the defaults in two servers collide exactly as two sessions in one server would. The device-side allocation is a capability question; `--port` is a client-routing question. The cost of the split is real too: more processes, more numbers to track, more supervision.

code

bash · 5 lines
bash
#!/usr/bin/env bash
# One Appium server per call-sheet lane: distinct front doors only.
appium --port 4723 --base-path /call-sheet-a &
appium --port 4733 --base-path /call-sheet-b &
wait

go deeper

for a junior

Learn that the Appium server's own --port and a session's device-side port capabilities are two separate things, and that a client URL is built on the first.

for a middle

Explain that one server can hold many sessions, and that each of those sessions still supplies its own appium:systemPort or appium:wdaLocalPort regardless of how many server processes exist.

for a senior

Weigh the operational trade: blast radius and per-lane logs against more processes and more numbers to manage, and be clear that neither shape removes the capability allocation.

for a principal

Decide the fleet's shape and say why: how many server processes a host runs, who supervises them, how leaked front-door ports are reclaimed, and where the per-session allocation scheme lives.

## Two different port questions A fleet running several Appium sessions at once has two port questions, and they are frequently confused because both are called ports. The first is *where the client connects*. An Appium server process listens on the port given by `--port`, optionally under a prefix given by `--base-path`, and a client is built on that URL. One server can hold many sessions at once, each with its own session id, all through one front door. The second is *how each driver reaches its agent*. Inside the server, the UiAutomator2 driver reaches its on-device server through `appium:systemPort`, and the XCUITest driver reaches WebDriverAgent through `appium:wdaLocalPort`. These are per-session capabilities on the device side, and they have nothing to do with which server process holds the session. Splitting servers answers the first question. It leaves the second untouched. ## What a server per session does fix - **Blast radius.** A server that dies, hangs or is restarted takes down its own session only, not every session on the host. - **Readable logs.** One process per lane means one log per lane, without several sessions' traffic interleaved into one stream. - **Routing.** A distinct `--port`, and a distinct `--base-path` when the servers sit behind one hostname or proxy, gives each lane a stable URL to address. - **Independent restarts.** A wedged lane can be recycled without disturbing workers that are mid-run. ## What it does not fix Nothing about the device side. Two servers started with different `--port` values will each happily create a session that asks for the default agent port, and the second one hits the same wall it would have hit inside a single server: on Android, two sessions competing for one `appium:systemPort`; on Apple platforms, two sessions competing for one `appium:wdaLocalPort` and possibly one `appium:derivedDataPath`. The web-view case is the same story with `appium:chromedriverPort` on the Android side, and the screenshot stream with `appium:mjpegServerPort` on both. This is worth stating plainly because the mistake is intuitive: separate processes feel like separate everything. They are not. The capability values are supplied by the client, per session, and they are what the driver forwards to the device. ## What it costs 1. Every extra server is another process to start, supervise and stop, and a leaked one holds its front-door port after the run. 2. Every extra server multiplies the numbers under management: a lane now owns a server port *and* a set of device-side ports. 3. Sessions in separate processes cannot be listed together from one server, so operational tooling that reads the running sessions has to visit each front door. ## Choosing the shape For a stage-crew call-sheet fleet the decision usually comes out like this: - One server, many sessions, when the workers are homogeneous, the host is stable, and a single log is worth more than the shared blast radius. The device-side allocation still has to be right. - One server per session when a lane can wedge the process, when lanes differ enough to want different server settings, or when an operator needs to recycle one lane without touching the rest. - Either way, the per-session capabilities are derived from the worker index and pinned. That step is not optional in either shape, which is the whole point of the question. ## What the split looks like from the client From the test side the difference is small and easy to underestimate. A worker built against a shared server points at one URL and asks for a session; a worker in the split shape points at its own URL. In both cases the request body is the same: `capabilities` carrying `platformName`, `appium:automationName`, the device selector and the per-session ports. Two consequences follow. - The harness needs a URL per worker in the split shape, so the server topology becomes configuration the suite has to carry. - Nothing about the capability map changes, so a suite moving from one shape to the other takes its port allocation across untouched, bug included. That second point is why the question is worth asking at all. The split is an operability decision, and it is a good one for some fleets, but it is never the answer to a device-side collision. ## The sentence to leave with A separate server changes who answers the client's HTTP request. It does not change which host port the driver forwards to the device. If a run collides today with one shared server, splitting it into one server per session and changing nothing else will produce the same collision through a tidier front door.

  • If a server per session does not fix the collisions, when is it still the right call?
    When failure isolation or operability is the goal. A wedged lane can be restarted without disturbing others, each lane gets its own log, and differing lanes can run with different server settings. Those are real gains — they are just not port-allocation gains, and the per-session capabilities still have to be derived and pinned either way.
  • What is --base-path for, if --port already separates the servers?
    It sets the URL prefix a server answers under, so several servers can sit behind one hostname or proxy and still be addressed unambiguously. It is a routing convenience for the client side. Like `--port`, it says nothing about the host ports a driver forwards to an Android or an Apple device.

saying these in an interview costs you the question

  • Believes a separate server per session removes the port capabilities
  • Thinks --base-path isolates the device-side ports
  • Assumes one Appium server cannot hold several sessions at once
  • Claims a server per session costs nothing on a shared host
  • Expects two servers to share one WebDriverAgent instance safely