What we collect. Where it lives. What crosses a border.
Minimum-data-by-design. The scan log is country + device-class only; there is no IP, no user agent, no cookie, no behavioral profile to leak. For regulated buyers who still need tighter placement, single-region D1 is available on Agency and Custom Enterprise — details below.
Data we collect
Every byte that ends up on our servers is in one of four buckets:
Account data
Email, plan tier, plan status, Stripe customer + subscription IDs, optional team name + workspace label. That's it. No phone, no address (billing address stays at Stripe), no behavioral profile.
Code data
The destination URL, a 7-char Base58 shortcode, a label + tags you set, optional QR design (colors / logo / frame), optional password gate, optional schedule. Owned by you; exportable as CSV any time.
Scan data
UTC day-bucket + country (from CF-IPCountry) + device class (mobile / tablet / desktop / unknown). Raw User-Agent is discarded immediately after classification. IP never enters the database. Cached in KV for the redirect hot path, aggregated into D1 via ctx.waitUntil. Country aggregates under 5 scans fold into "Other" to defeat re-identification.
Audit / billing metadata
Append-only log of mutations (who did what, when, in what scope) — 180-day retention. Stripe webhook events deduplicated for idempotency — no customer PII beyond the Stripe customer ID. GDPR request log (export / delete / restore) — retained past account deletion for on-time-honor proof.
For the full schema, see docs/SCHEMA.md in our source repo; every column is documented with a retention policy.
Where the data lives
| Surface | Provider | Region | Single-region option? |
|---|---|---|---|
| Dashboard + API | Cloudflare Pages Functions | Global edge (nearest PoP) | Yes — Agency+ only |
| Code records (D1) | Cloudflare D1 (SQLite) | Primary region assigned at provisioning (today: ENAM) | Yes — Agency+ per-tenant shard |
| Redirect hot path (KV) | Cloudflare Workers KV | Edge-replicated globally for <50ms p99 | Not available (replication is the product) |
| Encrypted backups | Cloudflare R2 | Primary region assigned at bucket create | Yes — EU / APAC jurisdictional bucket on request |
| Payments | Stripe | US — regional PII handling via Stripe's own residency | Via Stripe contract |
| Transactional email | ZeptoMail (Zoho) | IN (Zoho's EU region available on request) | Yes — Zoho EU region |
What crosses a border, exactly
- Scans never cross a border in a lossy way. A scan from Lisbon hits the Lisbon Cloudflare PoP, the worker writes day/country/device into KV at the edge, and aggregates async into D1 in its primary region. The original scanner's IP lives in Cloudflare's ephemeral request state for the duration of the HTTP request and is never persisted to our database.
- Dashboard requests terminate at the nearest Cloudflare PoP and call D1 over Cloudflare's private network. Our Pages Functions read/write D1 in its assigned region; the edge PoP serves the HTML + JS bundle from the global static-asset cache.
- Stripe webhooks cross the border once — Stripe (US) POSTs to our Cloudflare Pages endpoint, which verifies the HMAC, writes a minimal (event_id, type) row for idempotency, and dispatches downstream events.
- Transactional email (Zepto) crosses the border once per send — our worker hands a rendered template to Zepto's API; Zepto delivers to the recipient's mailserver. Content is invite links, billing-lifecycle notifications, and scan-cap alerts — no customer scan data.
Single-region residency (Agency+ and Custom Enterprise)
For EU-only or APAC-only buyers, Agency-tier customers can request:
- D1 placed in a single jurisdiction (EU: EEUR or WEUR; APAC: APAC). Cloudflare honors a
locationhint at database creation; we spin up a per-tenant D1 shard in the requested region (ADR-0010). - R2 bucket in the same jurisdiction — nightly encrypted D1 → R2 backups land in the matching region.
- Zepto EU region for transactional email — configured at the service level, no code change.
- KV stays global — edge replication is core to the <50ms redirect guarantee. If single-region KV is a hard requirement, talk to us; we can evaluate whether a regional-only Worker variant is feasible for your campaign.
Pricing for the single-region add-on is flat rate (no per-seat markup) and depends on the specific combination. Email enterprise@abundera.ai with your target jurisdiction + projected scan volume and we'll quote.
Compliance posture
- GDPR — minimum-data-by-design (country + device-class only, no IP, no UA, no cookies) plus one-click export and 30-day hard-delete. DPA + EU SCCs available for all paying tiers.
- CCPA — covered by the same export + delete surface. "Sale of data" is not a thing we do: no third-party sharing, no ad partners, no retargeting.
- SOC 2 Type II — in scoping. 6-9 month process. If this is a hard requirement for you, email enterprise@abundera.ai; we can share current status + projected timeline.
- PCI-DSS — out of scope for us directly; payments handled end-to-end by Stripe (PCI Level 1 certified).
Security disclosure
Found a vulnerability? Email security@abundera.ai. Coordinated disclosure — we'll acknowledge within 24h (business days), triage within 72h, and coordinate a fix + disclosure timeline with you. No bug bounty program yet; we do acknowledge researchers publicly at abundera.ai/security/thanks/ once a fix ships.