Case studies / Tigg Accounting · Feb – Mar 2026
Why a backup can't be a button
A company backup is requested, prepared, delivered and eventually expires. I designed and built the lifecycle so people can leave the page and still get their data.
Role
Timeline
Team
Platform
Not mine
Measured outcome
the key decision
The backup outlives the page: progress is resumable and the link also arrives by email.
how deep do you want to go?
Designing around leaving, not staying
I designed the backup page and built all of its frontend, plus the public page that an emailed link opens, between February and March 2026. The backend team built the backup job itself, the email and the retention rule.
Three decisions follow from "the backup outlives the page":
- The job is remembered. When a backup starts, the browser saves a small pointer: which job, for which organisation. Coming back to the page, or reloading it, shows "Reconnecting to backup status…" and picks up where it left off. The pointer is kept only if the organisation matches. Each organisation has its own address, and an accountant who works for several clients shouldn't see one client's backup on another client's page.
- The link arrives by email too. The backend emails a download link when the backup is ready, so nobody has to wait on the page. Small backups finish while the admin watches; large ones don't hold them there.
- One dropped check isn't a failure. The page checks the job's status in the background. A single failed check is ignored; four in a row are tolerated; only the fifth ends the wait.
Asset to add
Figma export: Tigg New Features → 'Backup Feature' page — the backup settings frame with the progress panel visible, 2x PNG
From a live stream to polling
My first version, on 11 February, listened to a live status stream from the server, and each step of the job updated the message on screen. Within the hour I replaced the inline delete confirmation with a proper dialog and added the saved pointer, so a reload no longer lost the job. Two days later I added the email-link download page.
Then the backend side ran into trouble. The senior backend engineer flagged problems with the live stream, so on 27 February I switched the page to asking for the status at intervals. On release day, 17 March, I tuned how often it asks: the checks settled at 3 seconds, then 10, then every 30. A small job reports back within seconds, and a long one costs only two requests a minute.
An honest word about the progress bar
Polling made progress coarse. The server reports how many of its parts are done, usually seven. Between checks, the bar would sit still for up to 30 seconds and then jump, which looks broken.
So the bar is partly estimated. It shows the larger of two numbers: the real share of parts completed, and a simulated value that creeps up in small random steps. The simulated value stops at a cap, and the real number is held at 99% until the server says the backup is complete, because the final step comes after the last part. At first the cap was 91%. It came down to 61% on release day, a change that also grew out of the backend problems the senior backend engineer raised. Looking back, the lower cap also stops the estimate promising "nearly done" while the job is still early.
I'm not fully comfortable with it. For most of a typical wait, the number is invented. The status messages cycle through a fixed set rather than following the real stage, so "Compressing data…" can appear before "Exporting products…". My first version tied each message to the part just completed, and I'd go back to that: show real stage names, keep the bar indeterminate until the server reports finer progress, and add a line saying it's safe to leave because the link will arrive by email.
Ready, downloaded, deleted, expired
When the job completes, the bar reaches 100%, a toast confirms it, and the new backup appears in the history table with its time, the person who started it, its status, and a download link. The download asks the server for a short-lived link at the moment of the click and then opens it.
The emailed link opens a public page that works on a phone, because that's where emails often get read. It has four outcomes: the link is invalid, the download is being prepared, the link has expired, or "Download started". If the person isn't signed in, they're sent to sign in and then brought back to the same link.
Deleting a backup opens a confirmation that repeats which backup is going ("Backup from 12-03-2026 10:14:05"), because the rows look alike, and says it can't be undone. Failed backups have no delete action. On release day I added the retention rule right above the table: "Backups expire after 5 days and will be removed from this list." Rows that disappear without warning look like lost data.
Asset to add
Screenshot, test company: the public backup download page on a phone — 'Download started' card, and the 'This backup link has expired.' card
Results and what I learned
The backup shipped in a beta release on 16 March 2026 and in a tagged release the next day, and it's in production. Measured outcome: none. I have no figures on how long backups take, how often people leave and come back, how often the page gives up while the server finishes anyway, or how many links expire unused. Those four numbers are what I'd instrument first.
Separate activity from measurement. The simulated fill made the wait feel alive, but for most of it the number was invented. Showing that work is happening doesn't require claiming how much.
Design the long wait around leaving. Resuming and the emailed link matter more than the bar, because they're what lets someone stop watching.
Name every ending. A long job can end in more ways than done or failed: the page can lose contact, or the server can forget the job. Each ending deserves its own sentence for the admin, for example "We lost contact. Your backup may still finish; check the history."
Iterations, edge cases and one neighbouring piece
Five weeks, dated
- 11 Feb 2026First versionPage, history table, live status stream, messages tied to each step. Within the hour: a delete dialog in place of the inline confirmation, the saved pointer, and resume on reload.
- 13 Feb 2026Email-link download pageThe public page, with sign-in and return to the same link.
- 27 Feb 2026Stream replaced by pollingPrompted by problems the senior backend engineer flagged. Simulated progress with a 91% cap and cycling messages arrived at the same time.
- 9 Mar 2026Tolerance for dropped checksUp to four failed checks in a row are ignored; the fifth ends the wait. Merged for testing the same day.
- 17 Mar 2026Release dayCap lowered to 61%; checks at 3, 10, then every 30 seconds; the 5-day retention note. I rewrote the page in a newer component style and reverted it seven minutes later; looking back, staying consistent with the codebase on release day was the safer choice.
Edge cases and how the page handles them
| Situation | What happens |
|---|---|
| Admin leaves or reloads mid-backup | The job continues; returning shows "Reconnecting to backup status…" |
| Admin switches to another organisation | No resume there; the saved pointer is left for its own organisation |
| One to four status checks fail | Nothing visible; checking continues |
| Fifth check in a row fails | The wait ends with an error, though the job may still finish on the server (a gap) |
| The server reports any part failed | "Backup failed" (or the server's message); no partial file is offered |
| The server no longer knows the job | The page stops quietly (a gap) |
| Repeated clicks on Backup Now | The button is disabled while a job runs |
| No history yet | "No backup history available. Click "Backup Now" to create your first backup." |
| Emailed link opened while signed out | Sign in, then back to the same link |
| Emailed link too old | "This backup link has expired." with a way back to Tigg or to support |
Nearby: who can see what, where
Later, in June 2026, I also designed a new permission editor. It shows organisation-wide and branch-specific access as two labelled regions, each with a count. I also wrote copy that separates a switched-off feature from a missing permission: "This is an organization setting, not a permission on the user you are editing." A frontend teammate integrated it into the branch-wise accounting release.
Notes on sources
No ticket or written rationale survives for the backup. The dates come from the version history; the reasons for the stream and cap changes come from my own account of the senior backend engineer's concerns. Other reasons given here are my reading in hindsight. Tigg's public changelog lists the backup feature on 9 February 2026, two days before my frontend work began; I take that as the announcement date. The diagrams are redrawn from the shipped page with fictional data.