File Server Agent: Bandwidth & Concurrency
The agent does not upload at a fixed concurrency. It watches its own recent upload outcomes and automatically adjusts how many files it uploads at once, backing off quickly when conditions look congested and recovering gradually once things improve.
Why this exists
Running uploads at a fixed concurrency works fine on a connection with headroom to spare. On a typical office uplink, though, sustained concurrent uploads can saturate the connection for hours, degrading everyone else’s internet with no visibility into why it was happening.
Manually configuring a per-client bandwidth cap is not a good alternative: it is a number nobody reliably knows, and one that does not adapt if conditions change. Instead, the agent runs an adaptive concurrency controller that learns the right level from its own upload outcomes as a job runs.
How it adapts
The controller adjusts concurrency the way network congestion control typically does: recovery is slow and incremental, backoff is fast and proportional. Concurrency is stepped up gradually when conditions look healthy, but cut back sharply as soon as conditions look congested.
This asymmetry is deliberate. A genuinely congested link should not oscillate rapidly between “fine” and “saturated” every few uploads, so climbing back up is made deliberately more cautious than backing off.
Throttling state is kept per backup job, not per configured share. That means a concurrency level already learned — up or down — carries over from one share to the next within the same job, instead of resetting to full speed every time the agent moves on to a new share.
Starting point and bounds
A job starts at its maximum concurrency level rather than starting low and ramping up. This is an intentionally optimistic default: most clients have plenty of upload headroom, and should not pay a slow-start tax for no reason.
The controller stays within a fixed floor and ceiling, so it will never drop to running one file at a time, and it will never exceed a sensible upper bound on simultaneous uploads.
Large files are uploaded in chunks, with a bounded number of chunks in flight for that file at the same time. This inner limit does not change on its own; the outer, adaptive file-level concurrency already reduces how many large files can be in flight at once, which reduces real total concurrency without the chunk-level limit needing to change too.
How congestion is detected
The agent judges network health over a rolling window of its most recent upload attempts, rather than reacting to any single slow or failed upload. A single flaky request is already absorbed by the agent’s own upload retry logic and does not, on its own, move concurrency in either direction.
Only a sustained pattern across the window triggers a decrease:
- A meaningful share of attempts timing out or failing, or
- Completed uploads coming in well below the best throughput recently seen.
When a decrease triggers, the current concurrency limit is cut back immediately, and the agent starts tracking for a return to healthy conditions before it will consider stepping back up.
Why throughput is judged separately for large and small files
Throughput is not compared against one single baseline. Upload outcomes are grouped separately for large, chunked files and small, single-shot files, and each group’s recent average is only ever compared against that same group’s own recent best — because a large file’s whole-file transfer rate is measured over minutes and often overlaps with whatever else is in flight at the time, while a small file’s transfer rate is a short burst measured in well under a second. Comparing the two directly would misread a job’s natural mix of file sizes as network congestion.
Each group also needs a minimum number of completed uploads in the current window before it is used to make a decision, so a real slowdown isn’t confused with what is simply normal for that group of files.
What triggers recovery
Recovery requires a sustained run of healthy windows in a row, with no congestion signal present in any of them. Only after that sustained run does concurrency step back up, gradually.
The count of healthy windows then resets, so the next step up again requires its own sustained run of good conditions. A single good window right after a decrease does not undo it; sustained health does.
Visibility on the dashboard
The agent reports its current effective concurrency on its existing mid-job status check-ins. When a job is running below its maximum concurrency, the operator dashboard surfaces this as a visible “Throttled” indicator on the job.
The indicator shows the current and maximum concurrency together with the reason:
- Slow network detected, or
- Upload errors detected.
This way, a job that is running slower than expected has a visible explanation instead of simply looking stuck.
See File Servers for what the agent backs up and how it enrolls, and Agent: Updates & Lifecycle for how the agent updates itself between backup cycles.