Snapshots

Most brand data is kept until someone asks us to delete it

Waiting on you
  • Six kinds of data have no end date, brand rows and the access log among them.
  • Delete my data promises 7 days; the privacy page gives no time.
  • The delete tool keeps no archive, only a record that a deletion happened.
  • Backups hold a deleted brand for up to 14 days, and are never restored for it.
  • Production has no deletion job yet; it arrives with the next promote.
7day deletion promise
Your call

Set brand data to end after 12 months without a sign in, with an email first?

Security, privacy and legal · 9.5

Retention and deletion

DraftLast checked 2026-10-26Owner Param

Answer

What we keep, for how long and how it is deleted; today most brand data is kept with no end date until someone asks, and this document proposes the periods the privacy policy will state.

Today

What is kept, and for how long

Data Where Kept Source
Session cookie fs_s The person's browser 30 days brew/auth.js:245
Sign in handshake fs_g The person's browser 10 minutes brew/auth.js:225
Session rows: email, browser, times sessions table Deleted 7 days after they expire brew/sessions.js:34
Who opened which brand access_log table, and visitors.json on bucket sites No end date; logging began 23 Oct brew/db/migrations/003_access.sql:19-30 memory brew-access-rules
Invites private/members.json Count for 14 days; up to 50 kept brew/auth.js:79, 102, 187
The read, facts, Plays, cards, memory, jams, briefs Brand rows in Cloud SQL, binaries in gs://brew-prod No end date handbook content/engineering/data-model.md
Stories Research pool 24 hours on the ring; 30 days and the newest 80 in the archive memory brew-stories-and-cards
Build progress lines build_events 3 days brew/server.js:724
Connected account keys private/vault/<id>.json, encrypted Until disconnect, which blanks the key brew/vault.js:20-30
A Shopify store's key and numbers Vault and live rows Dropped on shop/redact, 48 hours after uninstall, unless installed again brew/shopify-app.js:31, 204-216
Per customer Shopify records None kept Nothing to keep brew/shopify-app.js:18-19, 218
A record of each deletion data_deletions table: slug, request, operator, times, counts by folder, grants, what backups still hold; never contents or member names No end date; on staging now, production with the next promote brew/db/migrations/010_data_deletions.sql:1-18 brew/docs/production.md:95-97
Production database backups Cloud SQL Point in time 7 days; daily backups, 14 kept; one before every promote brew/docs/production.md:37-39
Nightly export gs://brew-prod-backups/nightly/brew.sql.gz Overwritten each night brew/docs/production.md:40
Files gs://brew-prod Old versions kept; 7 days soft delete brew/docs/production.md:12, 41
Staging bucket old versions gs://brew-prototype Deleted after 30 days memory brew-storage
Demo visitor sandboxes demo/<sid>/ Never cleaned, as of the 15 Oct audit brew/docs/handover/engineering/audits/E-accounts-demo-security.md:29

How deletion works

  • Delete my data opens an email to hello@joinsquareup.com and promises deletion within 7 days. brew/public/live.js:341-351
  • The privacy page names what goes, the read, Plays, jams and connected keys, with no time. brew/legal-pages.js:34
  • db/delete-brand.mjs deletes a brand for a data request on a Postgres site: every row under the brand with our stored tokens, workspaces, _deleted/ copies, build progress, jobs, bus, counters, access log rows, every bucket version of its files, and media only it points at. Dry run until --yes. brew/db/delete-brand.mjs:1-8; brew/db/brand-wipe.js:5-6
  • It keeps no archive, only the data_deletions row, and it writes that row before it starts, so an unfinished run shows. brew/db/brand-wipe.js:187-195, 222
  • File deletes remove every old version too, so object versioning keeps no copy. brew/db/brand-wipe.js:206-209
  • What still holds the brand for a while is printed for the reply: 7 days of point in time logs, 14 daily backups, the nightly export, and the bucket's 7 day soft delete. brew/db/brand-wipe.js:236-238
  • It refuses the five partners unless --partner-override --confirm-slug <slug>, and never deletes a brand in PROTECTED_CONNECTIONS. brew/db/brand-wipe.js:27-30
  • Production has no brew-prod-ops job and no data_deletions table yet; both come with the next promote. Until then a brand on production is deleted by hand. brew/docs/production.md:95-106; deploy state 26 Oct
  • tools/reset-brand.sh is bucket era and exits 3 on Postgres. brew/tools/reset-brand.sh:11-19
  • db/reset-jams.mjs clears jams only, never connections. brew/db/reset-jams.mjs:36, 53
  • Disconnecting inside the product, and the deletion tool, never revoke the grant on Shopify, Meta, Google, Slack or Klaviyo; the tool prints where the brand revokes each one. memory brew-wipe-data brew/db/brand-wipe.js:74-84, 240
  • The five partners are never wiped unless they ask, and Arata's Meta and Shopify connections are protected. memory brew-live-stores memory never-disconnect-arata-meta

Tomorrow

Proposed periods

Data Proposed period Version Tag
Brand data While the brand uses the service; deleted within 7 days of a request; a brand with no sign in for 12 months gets an email, then deletion 30 days later v1 New
Access log 12 months, then deleted v1 New
Session rows As today: 30 days plus 7 v1 Stays
Deletion audit row Kept as proof of the deletion; no contents v1 Stays
Backups As today: 14 days; a deleted brand is never restored from them v1 Stays
Demo sandboxes 7 days after the last visit v1 New
Raw page fetches 90 days v1 New, matches the data model proposal
Posts and schedules the brand approves While the brand uses the service v2 New
Measured results While the brand uses the service; they teach only that brand v3 New

Deletion tools

Item Version Tag
db/delete-brand.mjs: a dry run, then removes one brand's rows, parts, files and keys, with an audit row and no archive. On origin/main; production after the next promote v1 Stays
Delete one person: sign in, member rows, mail settings, jam authorship v1 New, proposed
Self serve deletion for admins v2 New

How we do it

  1. A request arrives at hello@; follow the runbook in data requests.
  2. Never delete a partner who did not ask. Never touch Arata's protected connections without Param.
  3. After a deletion, send the person the grants the run printed, to revoke themselves, and what backups still hold for up to 14 days.
  4. Check the access log size once a month until the 12 month purge exists:
gcloud run jobs execute brew-ops --region=asia-south1 --wait

db/status.mjs prints table sizes, access_log among them. memory brew-prod-backend

Numbers

Metric Definition Where measured Status
Days to delete Days from request to done reply hello@ inbox Proposed
Data with no end date Rows in the first table with no period This page 6 on 26 Oct
Access log rows Rows in access_log db/status.mjs Proposed

Open

  1. Brand data with no end date: do we set one? Proposal: 12 months without any sign in, then an email to admins, then deletion 30 days later.
  2. How long do we keep the access log? Proposal: 12 months.
  3. Do restored backups bring deleted brands back? Proposal: keep a list of deleted slugs and delete them again after any restore.
Sources
  • brew/sessions.js:19-34
  • brew/auth.js:79, 102, 225, 245
  • brew/db/migrations/003_access.sql:2-30
  • brew/vault.js:20-30
  • brew/shopify-app.js:18-19, 31, 204-218
  • brew/docs/production.md:12, 35-41
  • brew/public/live.js:341-351
  • brew/legal-pages.js:34
  • brew/tools/reset-brand.sh:11-19
  • brew/db/delete-brand.mjs:1-10
  • brew/db/brand-wipe.js:5-9, 27-30, 74-84, 187-195, 206-209, 236-240
  • brew/db/migrations/010_data_deletions.sql:1-18
  • brew/docs/production.md:95-110
  • brew commit e3e0fb4; deploy state 26 Oct
  • brew/db/reset-jams.mjs:36, 53
  • brew/server.js:724
  • brew/docs/handover/engineering/audits/E-accounts-demo-security.md:29
  • memory brew-storage, brew-wipe-data, brew-stories-and-cards, brew-access-rules, brew-live-stores, never-disconnect-arata-meta, prod-clean-only
  • handbook content/customer-success-and-support/data-requests.md, content/engineering/data-model.md

Source file content/security-privacy-and-legal/retention-and-deletion.md · For agents: Markdown · JSON