TopNetworksTopNetworks

Retention

What we hold, for how long, and what deletes it — 26 tables · 15 delete jobs · 10 no job touches. Every window in this table is read from the same module our delete jobs run on, so the policy and the deletion cannot drift apart.

Two clocks

Where a row has a window, it is a maximum of 7 days — operational and personal-linked rows alike — and that maximum is not a target: a row is deleted when its window closes, and where it can be let go sooner it is. 10 tables carry no window at all; the table below says which, and why.

Invoices, subscription and payment records are kept for 5 years because the ATO requires it — not because we want them. They are not logs. The 5 years is an obligation with a period on it, and it is the reason those rows carry no delete job in the table above: deleting them sooner would be failing the obligation, not tidying up.

Every table, and what removes it

One row per table in our database, including the ones we never delete. Where the enforced-by column names a job, that function is the only scheduled deletion for the row.

Retention by table
tablewhat it holdspersonal?classretentionenforced by
accountThe account itself: the name it is billed under, and when it was opened.yes — who pays, and what they pay forfinancialkept for 5 years for the ATO — no job deletes itno job — the ATO's period is an obligation, not a task
userThe person behind a sign-in: their email address, when it was verified, and whether they are a customer or an operator.yes — who pays, and what they pay forfinancialkept for 5 years for the ATO — no job deletes itno job — the ATO's period is an obligation, not a task
magic_linkA one-use sign-in link: a hash of the token, when it expires, and whether it was used.yes — a person, their browser or their addresspersonaldeleted after 7 dayspruneMagicLinks
sessionA signed-in browser: a hash of the cookie, its expiry, and the user-agent string the browser sent.yes — a person, their browser or their addresspersonaldeleted after 7 dayspruneSessions
planOur price list: the plan's code, name, price, billing interval and device limit.no — our own price listcataloguenot deleted — no job removes itno job — nothing deletes it
subscriptionA subscription: which plan it is for, its status, the processor's identifiers, and the end of the current period.yes — who pays, and what they pay forfinancialkept for 5 years for the ATO — no job deletes itno job — the ATO's period is an obligation, not a task
entitlementWhat a subscription unlocks: the feature, its limit, and when it was granted or revoked.yes — who pays, and what they pay forfinancialkept for 5 years for the ATO — no job deletes itno job — the ATO's period is an obligation, not a task
nodeOne of our machines: its name, region, hostname, public key, endpoint, tunnel pool, agent version and last heartbeat.no — our own machines and workersinfrastructurenot deleted — no job removes itno job — nothing deletes it
pop_deploymentOur ledger of the machines we have rented: the name, provider instance id and public address a PoP claimed. Never deleted, because a spent identity must not be handed back to the next machine.no — a routing change, a peer key and an instantlifecyclenot deleted — no job removes itno job — nothing deletes it
node_tokenThe credential our agent signs in with — a hash of the token only, and when it was revoked.yes — a credential or a device's identityidentitydeleted after 7 dayspruneNodeTokens
node_enrolmentA one-use token that enrols a new machine, and whether it was consumed.yes — a credential or a device's identityidentitydeleted after 7 dayspruneNodeEnrolments
deviceOne of your devices: the name you gave it, its public key, the tunnel address it was given, the counters the node last reported, and its handshake times.yes — a credential or a device's identityidentitydeleted after 7 dayspruneDevices
device_config_linkA one-use link that delivers a device's configuration: a hash of the token, when it expires, and whether the key was fetched.yes — a credential or a device's identityidentitynot deleted — no job removes itno job — nothing deletes it
node_eventA transition on a machine — a peer added, removed, moved or reset — with the peer key and the instant it happened.no — a routing change, a peer key and an instantlifecycledeleted after 7 dayspruneNodeEvents
node_healthOne poll of one machine: whether it was reachable, the latency we measured, its agent version, uptime and peer count.no — a measurement, not a personsampledeleted after 7 dayspruneNodeHealth
node_peerThe peers a machine reported in its last dump: public key, your address and port, the addresses allowed through it, the last handshake and the byte counters. Replaced on every report.yes — a person, their browser or their addresspersonaldeleted after 7 dayspruneNodePeers
peer_driftA disagreement between the peers we expect on a machine and the ones it reports, open until it stops being true.yes — a person, their browser or their addresspersonaldeleted 7 days after the row resolves — an open row is never deleted, whatever its ageprunePeerDrift
worker_runOne run of one of our workers: when it started, when it finished, whether it succeeded. Fleet-level — the row names no account and no machine.no — our own machines and workersinfrastructuredeleted after 7 dayspruneWorkerRuns
worker_leaseWhich worker is running right now, and until when.no — our own machines and workersinfrastructuredeleted after 7 dayspruneWorkerLeases
node_trafficThe sum of a machine's peer counters at one instant and how many peers that covers — a total, with no device identity on the row.no — a measurement, not a personsampledeleted after 7 dayspruneNodeTraffic
client_sessionA signed-in desktop client: a hash of its token, the name you gave the computer, and when it was last seen.yes — a person, their browser or their addresspersonaldeleted after 7 dayspruneClientAuth
client_device_codeA code a desktop client shows you, which you approve in a browser: hashes, the short code, and when it was spent.yes — a person, their browser or their addresspersonaldeleted after 7 dayspruneClientAuth
device_moveA device moved between machines: the machine, key and address it left, and the ones it arrived on.no — a routing change, a peer key and an instantlifecycledeleted after 7 dayspruneDeviceMoves
regionThe catalogue of places we sell: a code, the place's name, its country and a sort order.no — our own price listcataloguenot deleted — no job removes itno job — nothing deletes it
admin_viewA record of an operator opening the cross-tenant view: which address looked, at which page, when, and whether the gate allowed it. Nothing you typed.yes — a person, their browser or their addresspersonaldeleted after 7 dayspruneAdminViews
schema_migrationOur own ledger of which schema file was applied, and when.no — our own machines and workersinfrastructurenot deleted — no job removes itno job — nothing deletes it

The sharpest row we hold

The one thing in this database that is not anonymous, and the clock it gets instead of the seven-day one.

One row is sharper than the rest and gets its own clock. node_peer.endpoint is your real address and port as the machine last saw it — the least anonymous thing we hold. It is erased 24 hours after the address was last new information — when it changed, or when a handshake advanced — so a machine that keeps reporting the same address does not push that clock forward. The 7-day ceiling in the table above is a ceiling, not a target: an address does not wait for it. peer_drift.detail keeps a copy of that address, and that copy is erased 24 hours after the disagreement is detected or resolved, whichever is later — an open disagreement loses the address and keeps the row. The 7-day deletion for that row is a different clock: it counts from the moment the row resolves — 7 days after it resolves, not from the day it was detected — and an open row is never deleted, whatever its age.

What we never collect

Each of these is a statement about the schema, not a promise about intent — there is no column for any of it.

  • No traffic content, no packet capture and no deep packet inspection: we do not copy, store or read the packets that cross a tunnel.
  • No DNS query log: nothing we hold records the name you looked up.
  • No destination IP history: no row records where you connected. The only public address on a peer row is your own, and the paragraph above says how long we keep it.
  • No per-device traffic attribution: the throughput series is stored summed — node_traffic carries a total and a peer count, with no device identity on the row — which is why it needed none of the per-account scoping our peer table has (decisions/0034 D4). What a device row carries is the counter the machine last reported for it: a current value, not a window.
  • No keystroke, application or process monitoring: no column anywhere records what you typed, which program you ran, or what ran beside it.

One limitation, stated rather than omitted

Who can see across accounts, what the gate records when they do, and what it cannot tell you.

One limitation is ours to state, and we would rather state it than not. Four addresses hold the cross-tenant view — every account, every device, and which machine it sits on: [email protected], [email protected], [email protected] and [email protected]. They hold it because user.role is either 'customer' or 'admin': there is no read-only role between the two, and that limitation is real and it stays. What we can tell you is who opened it. Each time a signed-in session reaches the cross-tenant view, the gate writes the row to admin_view before it answers: the operator's address, the page that was opened, the instant, and whether the gate allowed it or refused it — a refusal is recorded too, because a role taken away mid-session is a fact worth keeping — and a write that fails is counted and reported to our own health checks rather than allowed to fail the page. The row is deleted after 7 days, counted from the view itself, on the same clock as the rest of the table above, so the answer reaches back exactly as far as this policy keeps anything. What it does not carry is the content: no query string, no body, no copy of your records, nothing that says which account or device was on the screen, and no address for the machine that asked, because we will not write a request header into a log as though it were one. So we can tell you which of the four opened the view, and when, for those 7 days; we cannot tell you what they read while it was open.