Security
Last updated 18 September 2026
In short
No badges, no vague reassurance. This is what is there and how it works.
- Your password is hashed with argon2id. We do not know it and cannot read it.
- All traffic between the app and the server is encrypted with TLS.
- A backup every night, read straight back to check that it is sound.
- Everything stays within the EU.
- No analytics package, no trackers, no advertising code in the app.
- Views of public lists are counted, with a token that cannot be traced to a person. See the privacy policy.
- No passwords in readable form, anywhere, logs included.
- No data leaving the EU.
- No promises we cannot keep. What we do not claim is at the bottom.
Your password
We do not store your password. What sits in the database is a hash made with argon2id, at the settings OWASP recommends: 19 MiB of memory and two passes. Argon2id is deliberately slow and memory-hungry, so someone who made off with the database could not compute their way through it.
In practice that means we cannot read your password, cannot send it to you and cannot give it to anyone else. Forgotten it? We set a new one; we cannot look up the old one.
The breached-password check
When you choose a password, we check whether it appears in a known breach. That happens without sending your password anywhere.
It works like this: your password is hashed locally and only the first five characters of that hash go to the service that tracks breaches. It sends back every hash starting with those five characters, hundreds of them, and the comparison happens on our server. So the other side never learns which password it was, or even whether there was a match.
If that service is down, your registration goes ahead anyway. Somebody else’s outage must not stop you making an account.
In transit
All traffic between the app and the server goes over TLS. There is no unencrypted variant to fall back to; a request over plain HTTP is redirected to the encrypted one before any content crosses the wire.
Signing in and staying signed in
You stay signed in with two kinds of token: a short-lived one for making requests and a long-lived one for renewing the first. The second is replaced on every use. If a spent token is presented again, which cannot happen by accident, we treat it as theft and end every session on that account at once.
On every request we also look the account up in the database again. That is what makes deleting an account take effect immediately, rather than whenever the last token happens to expire.
Who can reach what
The database separates users. Every beer, batch and group hangs off exactly one account, and the app never asks for anything without that account attached. A shared collection or a trade is an explicit exception you switch on yourself, and it gives access only to what you share.
The catalog is the one thing everybody sees, and that is the point: it holds facts about beers, not about people.
Stopping abuse
Signing in, registering, password resets and sending mail all carry limits per address and per IP. They are there to stop somebody guessing passwords or flooding a mailbox. A refused request does not say which limit was hit, because that would give something away in itself.
Beyond that, no answer from the server reveals whether an email address has an account. Registering with an existing address gives exactly the same answer as registering with a new one. The difference appears only in the mailbox of the person entitled to know.
Backups
Every night the database is dumped and then immediately read back to check that the dump is usable. A backup nobody knows works is not a backup. We keep fourteen daily and twelve monthly copies, and the restore procedure has been carried out for real once, against a separate database.
Where it lives
The server and the mail are within the European Union and fall under the GDPR. No data goes anywhere outside it.
Public lists are public
A list with a public code is meant to be found. It has its own address, it is listed in the directory, and it is indexable by search engines. There is no second switch that makes a public list unlisted: publishing one is the decision, and taking the code away in the app is how it is undone.
That is a change. The share page used to carry noindex and the code used to
sit in the part of the URL that never reaches a server. Both were there to make a public
page hard to stumble across, and a directory is the opposite of that.
Two things were kept when the code moved into the address, because they protect the link rather than hide the page:
- The code is not written to our access log. Requests to a share page
are logged as
/share/[redacted], and the referring page is dropped, so a link handed to one person does not end up recorded in a file. - The page sends no referrer. If you click a link on a shared list, the site you land on is not told which list you came from.
Private sharing is untouched by all of this. An invite code is not a public code: those lists are not in the directory, not indexed, and reachable only by the people you invited.
What a public page shows
Whatever the owner shared: the list’s name, their display name, and the beers in the locations they chose. Not their email address, not their account, and not anything they did not put in that list.
If something on a public page should not be there, there is a report link on the page itself. It needs no account and records nothing about you.
What this does not claim
Fair is fair. These are the things the section above does not assert, so you do not have to assume them:
- Your collection is not end-to-end encrypted. It sits encrypted on disk and travels encrypted over the wire, but on the server it is readable, because otherwise syncing between your devices could not work. Whoever runs the server can technically reach it. That is us, and we do not, but "we do not" is a promise rather than mathematics.
- The backups sit on the same machine as the database. They protect against a mistake of ours; they do not yet protect against losing the whole machine. An off-site copy is on the list and is not there yet.
- There has been no external audit. Nobody outside has reviewed this. What is written here is checkable, not certified.
- BackBeer is young. The app is not out of alpha. That is precisely the reason to write down how it works now rather than later.
Found something?
If you spot a hole, write to cheers@back.beer. Tell us before you tell anyone else, give us the chance to fix it, and do not pull other people’s data to make your point. We will answer, we take it seriously, and we will say what we did about it.
This page was written in Dutch. This English version is a translation provided for information. If the two differ, the Dutch text is the binding one.