GDPR
What Arkeion does for your data-protection obligations, what it leaves to you, and the one place where the design actively works against you. No product can make you compliant — compliance is a property of your processing, not of a database. So this page maps mechanisms to obligations and then says, in plain words, where the mechanism runs out.
This is not legal advice. It is a description of what the code does, written so your counsel can check it against the source.
Who is responsible for what
The GDPR assigns roles, and the role decides who owes what. Arkeion ships in two shapes, and they sit on opposite sides of that line.
If you embed the engine or run it yourself, we are not a processor. We never receive your data, there is no agreement to sign, and there is nothing about us you need to trust. The engine is MIT or Apache-2.0 and the file format is published, so nothing in that arrangement depends on our continued existence.
If you use Arkeion Cloud, Syrakon processes personal data on your instructions and everything in Article 28 applies to us: a written agreement, a sub-processor list, assistance with data-subject requests, and deletion or return at the end.
The erasure problem
Read this section twice before you put personal data in Arkeion. It is the one place where the engine’s central design decision works against a legal obligation, and no amount of wording makes it go away.
Arkeion is append-only with copy-on-write. Updating a row does not overwrite the
old row — it writes a new version and keeps the old one reachable through
AS OF. That is the whole point of the product, and it is exactly what
Article 17 does not want.
There is precisely one tool that removes history: vacuum, with a retention
policy. It takes three forms — keep everything, keep the last n versions, or
keep everything since a timestamp. All three are a global frontier.
The consequence is blunt. To guarantee that subject B’s historical versions are
gone, the frontier must sit above B’s last version — which discards every other
row’s history below the same line. Complete erasure of one person, with no
assumptions about where their data appears, means KeepLast(1): throwing away
the entire history of the database. There is no per-row, per-key or per-subject
purge, and we are not going to imply otherwise.
Two operational details that matter if you plan to promise anyone an erasure deadline:
vacuumrefuses to run while any branch other thanmainexists. An erasure request is blocked until you merge or drop the others.vacuumreturns busy if a write transaction is open, and it rewrites the whole file, so it needs roughly twice the database size in free space while it runs.
What “physical erasure” honestly means
vacuum builds a new file containing only the versions above the frontier and
renames it over the old one. Pruned versions are never written into the new file,
and AS OF below the frontier returns a version-not-found error rather than
data. That much is real, and it is more than a deletion flag.
But the old file is unlinked, not shredded. Nothing overwrites those blocks. On a copy-on-write filesystem, a snapshotted volume, or an SSD doing wear levelling, the previous bytes can survive on the medium long after the rename. So the accurate sentence is “removed from the database file” — not “destroyed on the disk”, and not “verifiably erased”. The vacuum report is our own count of what it dropped, not an attestation, and no test asserts that erased content is absent from the new file.
The pattern that actually works
The way out is not a feature request — it is a schema decision, and you have to make it before you write the first row.
Split identity from events. The identity table is small, holds the mapping from an opaque identifier to the actual person, and gets an aggressive retention policy — collapsing it to a single version costs almost nothing. The history table is the big append-only one and never contains a name, an email, or a free text field where someone will eventually type one.
An erasure request then deletes the mapping and vacuums the small table. The history keeps its hash chain and its full version record, and nobody can tell whose it was.
One caveat, because this is where the argument is usually oversold: this only reaches anonymity if re-identification is genuinely not reasonably possible afterwards. A history row carrying a postcode, a birth date and a rare diagnosis can identify someone with no name attached. Pseudonymised data is still personal data — the pattern moves you from “impossible” to “tractable”, not from “impossible” to “exempt”.
Crypto-shredding, and exactly what it buys
The standard answer to “append-only versus erasure” is crypto-shredding: don’t delete the data, destroy the key, and the ciphertext becomes noise. It is a good answer. It is also routinely claimed by products whose key granularity cannot support it, so here is precisely where ours does and does not.
The engine has one key per database. Encryption is page-level in the sense that a page is the unit sealed by each operation — one AES-256-GCM cipher per file, with the nonce as a per-page counter. It is not one key per page. And a page is a B-tree node holding rows from whoever happens to sort nearby, so the unit of encryption and the unit of erasure do not line up. Destroying the key does not remove a person; it removes the database.
That rules out shredding one data subject inside the engine. It does not rule out crypto-shredding — it moves the key boundary to the two places where it actually works.
One key per tenant — this is the one that solves backups
A managed database is a file, and a file takes a key. Give each tenant their own and destroying it makes their entire database unreadable everywhere that file exists — including in every copy taken before the request, on media nobody can enumerate any more.
That matters because backups are the part of Article 17 that most vendors quietly skip. A retention policy cannot reach a snapshot taken three months ago; a destroyed key can. It is end-of-relationship erasure — a departing customer, a terminated contract — not per-person erasure, and it is genuinely strong at that job.
One key per subject — above the engine, not inside it
When you must keep identifying data in the append-only history, encrypt it in your application under a key belonging to that person, and keep the keys somewhere you can really delete.
The keyring is small by construction — one short row per subject — so the retention frontier that is ruinous on a big table is trivial here: collapsing it to a single version costs almost nothing and takes no history worth having with it. That is the same trick as the pseudonymisation pattern above, one level stronger: there, you kept identities out of the history; here, you keep them in it but unreadable.
The four things that have to be true, or it is theatre
The key must not survive anywhere. Back up the keyring and you have undone the erasure without noticing. The keyring is the one thing in your system that must not be in your backups, and that is a deliberate, documented exception, not an oversight.
Keys must not be derivable. A per-subject key computed from a master secret plus the subject id is not shredded when you delete the row — anyone holding the master recomputes it. Generate them randomly and store them; do not derive them.
Metadata survives, and it is still personal data. Crypto-shredding destroys content, not existence. That a record existed, when it was written, how often it changed, how large it was and what it linked to all remain in the clear. If the shape of the data identifies someone on its own, this does not save you.
The legal status is defensible, not settled. The common reading is that data nobody can decrypt is effectively erased, and it is the position most of the industry operates on. It is not a universal regulatory ruling, and a supervisory authority can take a stricter view. Design for it, document it, and do not let anyone tell you it is a closed question.
Where this stands today
The per-subject pattern works right now, because it lives in your application:
the engine only ever sees ciphertext in a column. The per-tenant pattern needs
the daemon to accept a key, which it does not — arkeiond takes none, so a
served database is plaintext on disk. Until that changes, tenant-level
crypto-shredding is available to embedded and self-hosted deployments, and not
to the managed service.
What the hash chain proves
Every commit hashes the previous chain value together with the content hash,
version, timestamp and roots. verify() walks from genesis to head and reports
the exact version where anything fails. Flip one byte in one historical page and
it surfaces.
The chain is an unkeyed SHA-256 over public fields. There is no secret in it,
no signature and no message authentication code. Anyone holding the file can
recompute the whole chain from genesis after changing whatever they like, and
verify() will pass. The word for this is tamper-evident, and we will not use
immutable or tamper-proof anywhere on this site.
The mitigation is an audit anchor: a version number plus the chain hash at that version, forty bytes you capture and keep. Later, verifying against that anchor detects any rewrite of the history below it. Its entire value comes from where you store it — if it lives next to the database, it proves nothing.
Two limits worth stating: nothing is notarised, timestamped by a third party, co-signed or published to a transparency log, and the anchor check is not currently reachable through the network protocol, so it is a discipline for embedded and operator use today.
Encryption, exactly where it applies
The engine encrypts pages with AES-256-GCM when you supply a key. You pass thirty-two raw bytes; the engine has no key store and no derivation function, by design — custody stays with you. Each file derives its own subkey, so reusing a master key across tenants cannot collide nonces, and keys can be rotated by rewriting the file.
What this does not cover matters just as much:
- The daemon takes no key. Anything served over the network today is unencrypted on disk. Encryption at rest for a hosted product is a prerequisite we have not shipped, and until we do, no page here will claim it.
- There is no KMS, HSM or Vault integration. “Bring your own key” here means literally that you hand over the bytes. It is not enterprise key management.
- The unit is the page, and there is one key per database. Crypto-shredding an individual person is therefore impossible; destroying a key destroys the whole database, not one subject.
Article by article
| Obligation | What Arkeion gives you | What stays yours |
|---|---|---|
| Art. 5(1)(e) storage limitation | Retention policies enforced by compaction | The default keeps everything — you must set a policy on purpose |
| Art. 5(2) accountability | History is queryable evidence, not a claim | Deciding what the evidence needs to show |
| Art. 15 access | SELECT over the current or any past state |
Assembling the response; there is no export command |
| Art. 17 erasure | A global retention frontier | Schema design — see the section above |
| Art. 20 portability | Single file, publicly specified format, third parties can write readers | Converting to whatever format the recipient wants |
| Art. 25 by design | Pseudonymisation is natural if you split identity from history | Actually doing the split |
| Art. 30 records | Schema and version history | Access records — we do not log reads |
| Art. 32 security | AES-256-GCM at rest (embedded), TLS in transit, argon2id credentials, per-branch permissions | Key custody, and everything above the database |
| Art. 33 breach scope | AS OF states exactly what existed at a given moment |
Notifying, within the deadline |
| Art. 44+ transfers | EU hosting, French jurisdiction, European ownership | Your own onward transfers |
Questions from sceptical buyers
“Append-only and the right to erasure are incompatible. How do you square it?” For the most part we don’t, and the section above says so with a diagram. The frontier is global. The workable answer is to keep identifying data out of the append-only history in the first place, which is a schema decision you make on day one and cannot retrofit cheaply.
“Is vacuum real erasure or a flag?”
Real, in the sense that pruned versions are never written into the new file and
become unreadable through AS OF. Not real in the sense of shredding: the old
file is unlinked, not overwritten, and its blocks may persist on the medium.
“You say you don’t access our data. You’re root on that machine.” Correct. On the managed tier, “we don’t access it” is a commitment backed by isolation and an audit trail — it is a policy, not a physical impossibility. The version where we cannot read it needs a confidential enclave, and that is on the roadmap, not shipped. We keep those two words apart everywhere on this site because the difference is the entire point.
“Is my database encrypted at rest in Cloud?” Not today. The daemon takes no key. That is a gap we have to close before a hosted product can be sold on a security argument, and we would rather say it here than let you discover it in a security review.
“Can you crypto-shred a single customer?” Not inside the engine: one key per database, and a page holds rows from many people, so destroying the key destroys the database rather than a person. You can do it above the engine with a per-subject key and a keyring you actually delete — the section above sets out the pattern and the four conditions that have to hold for it to mean anything. At tenant granularity it works directly, and that is the version that reaches your backups.
“Your chain is unsigned. I could rewrite it.” If you hold the file, yes — and so could we. That is why it is called tamper-evident. Capture an anchor, store it somewhere we cannot reach, and the guarantee becomes real for everything below that point.
“Do you log who read what?” No. There is no access logging today, reads leave no trace, and commits carry no actor identity — the chain records what changed and when, never who. If your obligations need access records, you must produce them above the database.
“How do I delete from your backups?” There is no backup product, and nothing propagates a deletion into copies that already exist. This is a hard problem for everyone in the industry; we would rather admit it than pretend a retention policy solves it.
“Are you ISO 27001 or SOC 2 certified?” No, and we have not applied. If a certification is a hard requirement for you, we are not a fit yet.
“What happens to our data if Syrakon disappears?” The engine is MIT or Apache-2.0, the file format is publicly specified on this site, and your database is a single file you already hold. You can keep running it, or write your own reader from the specification. This is the one continuity question we can answer without asking for any trust at all.
“Sub-processors, and the US CLOUD Act?” Hosting is European under French jurisdiction, and ownership is European — which is the part that actually matters, since a US-owned provider is exposed regardless of which region you pick. Cloud is not open yet; when it opens, the sub-processor list is published with the agreement.
“Can we get everything out?”
Copy the file, read it with an independent implementation, or SELECT it out
through the driver. There is no one-command export and no CSV, JSON or SQL data
dump today — the schema dumps, the data does not.
“Do you phone home?” No telemetry, no usage reporting, no network calls the engine makes on its own.
What we do not claim
- Not “GDPR compliant” — no database can sell you that.
- Not immutable, not tamper-proof: tamper-evident.
- Not notarised, anchored by a third party, or signed.
- Not encrypted at rest when served over the network, today.
- No per-subject erasure inside the engine, and no key management product. The crypto-shredding above is a pattern you implement, not a feature we ship.
- No access logs, no managed backups, no one-click export.
- No security certifications.
Everything on this page is checkable against the source, which is the only reason to believe any of it. If you find a claim here that the code does not support, that is a bug and we want to hear about it.