Why we don't keep a copy of your address book
The obvious way to build a contact-sharing product is to import everything. Pull every contact from every connected account into your own database, treat that as the source of truth, and push changes back out. It makes the engineering easier: queries are fast, you control the schema, and sync becomes “diff my database against theirs.”
We deliberately did not build Rolyio that way. Your contacts live in Google and Microsoft. Rolyio stores the sharing relationships and permissions — the links between copies of a contact across accounts — not a mirror of your address book. This post explains what that means concretely and why we think it is the right trade-off.
What we actually store
When you connect an account and share a label, Rolyio’s database holds:
- Account records and OAuth tokens — the tokens encrypted at rest with AES-256-GCM.
- Label metadata — a thin layer over the provider’s real structures. A label is a Google contact group or an Outlook category; we store which group/category it maps to and who it is shared with.
- Shares and roles — who has View, Edit, or Can reshare on which label, including pending shares for people who have not signed in yet.
- Link clusters — the record that says “contact X in the owner’s Google account and contact Y in a recipient’s Outlook account are the same person.” This is the core of the system: identity mapping, not content storage.
- Sync state — incremental sync tokens, change fingerprints for echo protection, and timestamps for conflict resolution.
What is not there: a table of your contacts. When sync runs, contact data flows through the sync engine from one provider account to another, guided by the links and roles — it does not settle into a warehouse on our side.
There is one deliberate, bounded exception: when a shared contact is deleted, we keep a snapshot in Trash for 30 days so that an accidental deletion — yours or a teammate’s — is recoverable. After 30 days the snapshot is purged. That is a safety net with an expiration date, not a shadow address book. (You can also purge it yourself; see trash and restore and delete your data.)
Why links beat mirrors
A smaller breach surface
Security architecture starts with an uncomfortable assumption: any system can be compromised. The question is what an attacker gets. In a mirror architecture, the answer is every contact of every customer — names, phone numbers, relationships — sitting in one database. In a links architecture, the contact data an attacker would want simply is not there to take. What exists is metadata: which labels are shared with whom, plus encrypted tokens whose key lives separately from the database.
We would rather not be a honeypot. The least risky data is the data you never stored.
No second source of truth
Every mirror eventually disagrees with its origin. A mirrored contact database and Google’s copy will drift — a failed sync here, a race condition there — and then the product has to decide which version is real. Users lose either way: either the tool shows stale data, or worse, it “fixes” the provider’s copy with its own stale version.
By keeping the provider authoritative, Rolyio sidesteps the whole category. What you see in contacts.google.com or Outlook is the truth. Create a contact group in Google and it appears in Rolyio; rename a label in Rolyio and it renames in Google. The sync engine’s job is moving changes between providers’ copies — with last-write-wins conflict handling that respects roles, and fingerprint-based echo protection so our own writes are never mistaken for user edits. The mechanics are documented in how sync works.
Sharing that ends when it ends
Links have another property mirrors lack: they are cheap to sever, completely. When you unshare a label, Rolyio removes the shared contacts from recipients’ address books and drops the corresponding links. There is no residual copy of the recipient’s view sitting in our database, because there never was one. Revocation is subtraction, not a cleanup project.
The same logic applies if you leave Rolyio entirely. Your address book was never in our hands, so there is nothing to export back or trust us to erase — deleting your account deletes relationships and encrypted tokens, and your contacts remain exactly where they always were: in your Google or Microsoft account.
What it costs us
Honesty requires listing the downsides, because we pay them daily:
- Sync is harder to build. Without a central copy, every operation reasons about N provider-side copies connected by links. Conflict resolution, deletion semantics (tombstones that respect roles), and dedup by email all have to work in a distributed setting.
- We inherit provider limitations. Google offers no push notifications for contacts, so the Google side syncs by polling roughly every 60 seconds with incremental tokens. Microsoft Graph gives us webhooks, so the Microsoft side is near real time — but Graph will not let us rename a category. A mirror could paper over such asymmetries; we surface them and design around them.
- Some features are simply off the table. Anything that requires analyzing your full address book server-side conflicts with not having your full address book. We consider that constraint a feature.
The test we apply
When we evaluate a new capability, the question is: can this be built from links, roles, and provider APIs, without accumulating contact data on our side? If yes, we build it. If no, we look for a different shape. Cross-ecosystem sharing between Google Workspace and Microsoft 365 — the product’s defining feature — passed that test: it needs identity links across ecosystems and role-aware sync, not a central contact warehouse.
If this architecture matches how you think infrastructure should treat your data, connect an account and look at what we ask for — the incremental OAuth scopes tell the same story as this post.