All articles
QA MaestroAppiumMobile AutomationFlakiness

How Maestro Works Under the Hood, and Why Its Tests Are More Stable Than Appium's

Both touch the app from the outside, so where does the stability gap come from? A look at what happens between a test line and the screen in Maestro and Appium, and when to pick each.

8 min read

Maestro and Appium reach your app in almost the same way: from outside the app, through the screen-automation tools Google and Apple provide, as if they were a finger touching the screen just like a user would.

The real difference is somewhere else: how many stops a command passes through before it reaches the screen, and who's responsible for the waiting. And that's exactly what decides whether your test passes ten times out of ten, or only eight.

The same test, two ways

Let's take one scenario and follow it all the way through: a shop app, you open it, tap the Login button, and check that the word Welcome appears.

In Appium you write the test in a programming language, Java for example:

WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
wait.until(ExpectedConditions.elementToBeClickable(
    AppiumBy.accessibilityId("Login"))).click();
wait.until(ExpectedConditions.visibilityOfElementLocated(
    AppiumBy.accessibilityId("Welcome")));

And in Maestro you write a YAML file:

appId: com.example.shop
---
- launchApp
- tapOn: "Login"
- assertVisible: "Welcome"

Notice that the Appium code is full of the word wait. That's not a coding style — it's the heart of the whole difference, and we'll come back to it shortly.

What happens behind the scenes in Appium?

When the click() line executes, the command passes through five stops:

  1. The test code turns the command into an HTTP request in the WebDriver format — the same format Selenium uses.
  2. The Appium Server receives the request on your machine or on CI, and decides which Driver will handle it.
  3. The Driver translates the command: the UiAutomator2 Driver on Android, and the XCUITest Driver on iOS.
  4. A helper program installed on the device actually executes the command: on Android it's a server built on Google's UiAutomator, and on iOS it's WebDriverAgent, built on Apple's XCTest.
  5. The app receives the tap, like any tap from a human.

The fourth stop is the important one: this helper program isn't inside your app. It's a separate program on the device that reads the screen through the Accessibility layer and sends taps from the outside. So in its usual setup, Appium also touches the screen from the outside — but here the tap comes at the end of a long chain.

Info
There is one Driver that runs inside the app: the Espresso Driver on Android. It has to be built together with the app itself, and it can tell when the app is busy. But it isn't the default, and most of the Appium projects you'll see in companies use UiAutomator2 and XCUITest.

And what happens in Maestro?

The tapOn: "Login" command passes through fewer stops:

  1. The YAML file is read directly by the Maestro CLI — no Compile step and no programming-language library.
  2. The Maestro CLI talks directly to a small program it installs on the device.
  3. This small program is also built on UiAutomator on Android and XCTest on iOS. Yes, the same foundation Appium relies on.
  4. The app receives the tap.
Appium — five stops Test code Appium Server The Driver Device helper The app Maestro — four stops YAML file Maestro CLI Device helper The app The last two stops are the same: both touch the app from the outside

So the difference isn't in how the tap reaches the screen. The difference is in what happens before the tap.

So where does stability actually come from?

Most unstable tests — what we call Flaky Tests — aren't caused by the tool tapping in the wrong place. They're caused by timing: the tool tapped the button before it appeared, or before the animation moving it into place finished, or before the server response came back.

This is where the two tools are designed differently.

In Appium, waiting is your responsibility. Every place in the app with loading or animation needs a suitable wait written for it. If you forget one, or pick a timeout that's too short, the test passes on your machine and fails on the slower CI. If you pick one that's too long, the test becomes slow. And plenty of teams give up and write Thread.sleep, which is the worst solution of all.

In Maestro, waiting is part of the tool. Before every step, Maestro waits for the target element to appear, and waits for the screen to settle — meaning animations and loading have stopped. And if it doesn't find the element right away, it retries on its own for a reasonable time before declaring failure. You don't write a single line of waiting.

There's another, less obvious reason: every extra stop is an extra chance for problems. In Appium, the Server, the Driver, and the helper program each have their own version, and those versions have to be compatible with each other and with your Android or iOS version. Most "the test was working yesterday" messages come from here, not from the app.

Important
Maestro reduces flakiness a lot, but it doesn't eliminate it completely. If the app itself is unstable, or the test data keeps changing, or the elements have no text and no clear Accessibility IDs, you'll hit the problem in any tool. A good tool protects you from timing issues, not from a badly built app.

So is Maestro better than Appium at everything?

Not at everything. Here's the honest picture:

Question Maestro Appium
Who writes the tests? Anyone who can read YAML: a Tester or a PO An engineer writing code in a programming language
Waiting Automatic, built into the tool You write it for every step
Setup One tool you install and go Server, Drivers, a library, and configuration
Speed of writing and trying Save the file and it re-runs instantly Compile, then run
Complex logic Limited, with the option of small JavaScript scripts Full, because it's real code
Ecosystem Newer and smaller Huge, and supported on every cloud device platform

Choose Maestro when your goal is to cover the core user journeys quickly and reliably: sign-up, login, checkout, and search. And when your team has non-programmers you want writing tests.

Stay with Appium when you already have a large test suite written, or you need complex programming logic inside your tests, or you depend on tools and platforms built around WebDriver.

And many teams use both: Maestro for the core journeys that must never fail, and Appium for the special cases.

Summary

  1. Both touch the app from the outside in the usual setup, through the same Google and Apple tools. The only exception is Appium's Espresso Driver, which runs inside the app.
  2. Appium goes through five stops, and Maestro through four, and every stop fewer means fewer compatibility problems.
  3. Stability comes from smart waiting. In Maestro it's part of the tool; in Appium it's your responsibility on every line.
  4. Maestro isn't a replacement for everything. It's the fastest and most stable option for user journeys, while Appium stays stronger for complex logic and large systems.

If you want to see this in practice — from installation on Windows and macOS to running tests on Maestro Cloud and wiring them into CI/CD and iOS — that's exactly what the Mobile App Test Automation with Maestro course covers: sixty-six video lessons, without a single line of code.

Want to go deeper?

This article gives you the idea. The courses take you from zero to actually doing it.

See the courses