Testing NTN Apps Without Waiting for a Satellite Pass

NTN Satellites

I have been thinking about NTN from a very practical angle: if an app is supposed to work over satellite, how do we test it before the real network is available?

That sounds simple, but it is not. A satellite link is not just “slow internet”. It can be available for a short window, become worse near the edge of coverage, disappear completely, and come back later. If we only test with normal Wi-Fi or a basic offline toggle, we miss a lot of the behavior that matters.

That is why I started NTN-in-a-Box.

The goal is not to simulate the radio layer. There are already good projects for PHY and RAN research. I wanted something closer to the developer workflow: run an app, put it behind NTN-like conditions, and see what breaks.

NTN-in-a-Box GUI showing satellite pass visualization and live link metrics

What it does

NTN-in-a-Box creates a local sandbox where the network changes over time. A profile can describe things like:

  • coverage windows
  • latency and jitter
  • packet loss
  • bandwidth limits
  • when the next window starts or ends

On Linux, it can run a command inside a shaped network namespace. That means the application does not need to know it is being tested. Requests get delayed, dropped, or timed out by the sandbox.

For example:

1
2
3
4
5
6
go build -o ntnbox ./cmd/ntnbox/
go build -o poller ./cmd/poller/

sudo ./ntnbox run \
  --profile testdata/profiles/leo_pass_90s.yaml \
  -- ./poller

During the pass, the poller starts with a usable but not perfect link. The link improves, then degrades, then disappears. When the next window opens, it recovers. This is the part I care about most: not just “does the app work”, but “does the app recover cleanly after a weird network period”.

Why this matters

Most apps still treat connectivity as a yes/no state. NTN is more annoying than that. The app may technically be online, but the next two minutes might be a terrible time to upload a large file. Or the app may be offline now, but a short window is coming soon and queued work should be ready.

Those details change application behavior. I want to test questions like:

  • Does retry logic back off, or does it hammer the link?
  • Does the app queue messages locally when coverage is gone?
  • Does it flush the queue when the window returns?
  • Does it avoid starting a large transfer when the window is almost over?
  • Can the UI explain what is happening instead of showing a generic failure?

These are not only telecom problems. They are product and UX problems too.

The project includes small sample apps for things like adaptive polling, offline queues, store-and-forward messaging, Android emulator testing, and CI replay. They are intentionally simple because I wanted the failure mode to be visible.

TLE support

Static profiles are good for repeatable tests. For example, “give me a 90 second LEO-style pass every 10 minutes” is perfect for CI or demos.

But I also wanted to play with real satellite orbit data, so NTN-in-a-Box supports TLE files. You can generate a profile from a TLE and an observer location:

1
2
3
4
5
./ntnbox tle generate \
  --file testdata/tle/iss.tle \
  --lat 37.7749 \
  --lon -122.4194 \
  --output iss-pass.yaml

Or you can run from predicted passes directly:

1
2
3
4
5
6
7
sudo ./ntnbox run \
  --tle testdata/tle/iss.tle \
  --lat 37.7749 \
  --lon -122.4194 \
  --start-at next-pass \
  --speed 10 \
  -- ./poller

The GUI shows the orbit, the observer, and the coverage beam. It is not meant to be a mission planning tool, but it makes the pass feel much more real than a YAML file.

NTN-in-a-Box TLE globe visualization showing orbit, observer, and coverage beam

This is useful when the scenario is tied to a location or a specific satellite, not just a synthetic “good link / bad link” timeline.

API-first testing

Not every test needs traffic shaping. Sometimes the application just needs to know what the satellite state looks like and make a better decision.

NTN-in-a-Box exposes a local API for that:

1
2
3
4
5
6
./ntnbox serve --profile testdata/profiles/leo_pass_90s.yaml

curl http://localhost:8080/devices/sandbox-0/condition
curl http://localhost:8080/devices/sandbox-0/lookahead
curl http://localhost:8080/devices/sandbox-0/capabilities
curl -N http://localhost:8080/events

An app can ask:

  • Am I in coverage right now?
  • How long until the next transition?
  • What is the current delay, jitter, loss, and bandwidth?
  • Is a usable window coming soon?

This is where the developer workflow becomes interesting. You can build a countdown, delay a sync job, show a better message to the user, or test store-and-forward behavior without needing access to a commercial NTN environment.

Android and mobile workflows

Android already has NTN-related platform work, but most developers cannot easily test the behavior end to end. NTN-in-a-Box has two paths for this.

On Linux or WSL2, you can shape emulator traffic directly. On macOS, you can still expose the API to the emulator with adb reverse and test how the app responds to coverage changes.

I like keeping those two modes separate:

  • traffic shaping tells you whether the network path actually fails and recovers
  • the API path tells you whether the app understands NTN state and reacts properly

Both are useful. They answer different questions.

CI and replay

One feature I like is record and replay. If a test fails during a simulated pass, I do not want to explain it with “well, the network was weird”. I want to replay the same weirdness.

1
2
./scripts/demo.sh --record session.jsonl
./ntnbox replay --file session.jsonl --speed 10 -- ./my-app

There is also a GitHub Action so a team can wrap normal tests in an NTN profile:

1
2
3
4
- uses: hyavari/ntn-in-a-box@v1
  with:
    profile: leo_pass_90s
    command: npm test

The command still exits like a normal test command. The difference is that it ran through a network condition that looks more like the real world we are trying to prepare for.

Where it fits

I see NTN-in-a-Box as a small bridge between telecom concepts and everyday software testing.

For telco engineers, it is a way to explain coverage windows and constrained links without needing a full network setup. For app developers, it is a way to test ugly network behavior before users find it. For platform teams, it can help design APIs and UX around intermittent connectivity.

The project is still early, but that is the direction: make NTN conditions easy to run locally, easy to observe, and easy to repeat.

You can find the project here:

https://github.com/hyavari/ntn-in-a-box

updatedupdated2026-07-142026-07-14