Changelog

Everything we ship to BucketPilot — new features, and the fixes worth knowing about.

Migrations

Server-to-server migrations, an order of magnitude faster

Transfers now pipeline their SFTP requests instead of waiting for one round trip at a time, and a large tree starts copying in seconds rather than minutes.

Copying between two of your own machines was bound by network latency, not by bandwidth or by our workers: every chunk waited for the previous one to be acknowledged, on both hops. On a link with 30 ms of latency that caps a transfer at roughly 1 MB/s no matter how fast the pipe is.

Transfers now keep 64 requests in flight per file, in both directions. Measured on a zero-latency loopback — the floor of the improvement, not the ceiling — throughput went from 28.9 MB/s to 66.4 MB/s with byte-identical output. Over a real internet link the gain scales with the round trips removed.

Three more things that were quietly costing whole minutes:

  • Scanning a deep tree walked one directory at a time and asked the server to describe every file it had already described. Directories are now scanned in parallel, and the live view reports Scanning /var/www — 12,480 files so far instead of a silent "Scanning remote directory…".
  • Re-runs checked the destination one file at a time. The destination is now read once, up front, and compared in memory — on a 24,000-file job that replaces 24,000 sequential round trips with a few hundred concurrent ones.
  • Server-to-server runs use 4× the thread count you pick. Those runs wait on two remote machines rather than on our workers, so the plan's number is a floor, not a ceiling: Pro copies 16 files at once, Business 32. The picker tells you what the run will actually do.

See the migration guide for how jobs work.

Migrations

Migrations copy the whole tree — symlinks and empty folders included

Two ways a server-to-server copy could silently leave holes in the destination, both closed.

If your source tree reached a directory through a symlink/var/www → /srv/app, current → releases/2026-07, the usual shapes — the listing treated it as a file, failed it, and never copied anything beneath it. Links are now followed: a linked directory is walked, a linked file is copied at its real size, and a link pointing back into the tree is skipped rather than copying the same data twice.

Empty directories appeared in no file listing at all, so they simply weren't recreated. A server destination now gets the shape of the source tree, not just its files.

If you ran a server-to-server job before today, run it again — it will copy exactly what was missed and skip everything already in place.

Jobs

Jobs that finish, and a detail page that keeps up

Runs no longer hang at 100%, the detail page updates without a refresh, and every job can be deleted from where you're standing.

A migration that hit an unreadable file could sit at running, 100% until the 24-hour reaper stopped it. The underlying cause was an error that our SSH library reports on the connection rather than on the file's stream, where nothing was listening — the transfer then waited forever on a source that would never speak again. Those files now fail as ordinary per-file errors and the run completes with them listed.

Also in this release:

  • The progress bar counts files that are finished, not files that have been picked up, so it no longer reads 100% while the last few are still transferring.
  • The job detail page polls while a run is queued or running — the status and log used to freeze until you reloaded the page.
  • Opening a job from the Jobs table used to be able to show you a different job: backup and migration ids are issued independently, so the two could collide. Links now carry the job's kind.
  • Delete is available on the Jobs table and on the job detail page, not only on the job cards.
  • The thread count, schedule, source server, paths and destination of a migration job are all editable now. Previously changing where a job pointed meant deleting it and building it again.
Analytics

Per-server activity in Analytics

Every machine your migration jobs touch, with the jobs attached to it, its runs and the bytes it moved in the last 30 days.

Analytics gains a Your servers table: one row per machine, showing the jobs attached to it (as a source or a destination), how many runs it took part in over the last 30 days, how much data moved through it, and when it last ran with the result.

This is built from data we already keep about your jobs — we don't connect to your machines to collect metrics, and nothing new is stored.

The same release adds activity cards by category — uploads, jobs and migrations, buckets, credentials and servers, security, billing — so the page reflects what the workspace has been doing, not only what it's storing.

Platform

"SFTP server" is now just "Server"

The machines you migrate to and from are called servers throughout the product, and the firewall address you need to allow is on screen where you need it.

The protocol was leaking into the product's vocabulary. A machine you own is a Server now — in the migration form, on the Credentials page (the tab is Servers), on the landing page, in the plan comparison and throughout the docs. The API is untouched: sourceType: "ssh", sshServerId and the rest are unchanged, and the API reference still documents them as they are.

Alongside it: jobs always connect out from one fixed address, and that address is now shown where you'd want it — in the migration form, in the Add Server dialog and in the migration guide. You can allow a single IP on your SSH port instead of opening it to the internet.

Migrations

Pull an offline copy of a bucket onto your own server

A migration job can now read from a managed bucket and write to a machine you own.

Migration jobs have always moved data into a bucket. On the Business plan they now go the other way too: pick a bucket as the source, a server as the destination, and an optional key prefix to limit what's copied.

It rides the same machinery as every other job — incremental re-runs, streamed transfers so file size isn't a limit, atomic writes that never leave a half-written file, and host-key pinning on the destination.

Bucket → bucket is deliberately not offered here: that's a backup job, which compares ETags and does it better.

Buckets

Connecting a bucket: discover or create, nothing in between

One guided flow for existing buckets, with honest handling of credentials that can't list them.

Adding a bucket used to offer two doors that did nearly the same thing. Now there are two that don't overlap: Discover finds what a credential can see, and Create Bucket makes a new one.

Credentials that legitimately can't list buckets — Google Cloud Storage, scoped R2 tokens, least-privilege AWS policies — get a guided card with an inline "add it by name" form instead of an empty list. A bucket added by name is verified before it's registered, so a typo returns a clear error rather than a bucket that appears to exist and fails on first use.

Other rough edges from the same release: a bucket deleted at the provider now says so plainly, browser uploads apply their CORS rule automatically on first use when none exists, and creating a bucket on a provider without versioning no longer offers it.

Platform

A getting-started checklist that reads your actual account

Four steps, derived from what you've really done rather than from a tour you clicked through.

New accounts land on a dashboard panel with four steps — connect a credential, add a bucket, index it, run a job — each derived from live account state. Finish a step anywhere in the product and it ticks itself; dismiss the panel and it stays dismissed.

Each step hands off to the next: saving your first credential forwards you to bucket discovery, and importing buckets points at indexing. Sign-up no longer asks for a username either — one is minted for you and can be changed in Settings whenever you like.

Teams

Audit log export with date ranges

Export the activity feed as CSV for the last 24 hours, 7 or 30 days, all time, or any range you pick.

The Business audit export gained a range picker: quick presets for 24 hours, 7 days and 30 days, all-time, or a custom range from the calendar. The file is named with the dates it covers, so a folder of exports stays legible.

The CSV carries timestamp, actor, action, bucket and job for every event in the workspace — including denied permission attempts. See Security & privacy.