Choosing a storage backend
Every Gutternote comment has two halves:
- The anchor — which page, which element, where on it, and whether it’s resolved.
- The body — the prose someone wrote, who wrote it, and any attachments.
Anchors are always stored by Gutternote. That isn’t a policy position, it’s what makes the product usable: rendering forty pins on page load has to be one indexed query, not forty round trips to a rate-limited third party. Anchors are coordinates and status flags, not content.
Bodies are yours to place.
The three backends
Gutternote Postgres — the default
Everything in our database. Full feature set, fastest reads, simplest operationally. Choose this unless you have a specific reason not to.
Your GitHub repo
Bodies become issue comments in a repo you own, via a GitHub App. Gutternote keeps the anchor and the issue number, and nothing else.
Good when your objection is “comment text must not sit in a vendor database” and your commenters all have repo access anyway.
Know the trade-offs before you pick it:
- No attachments. GitHub has no supported API for programmatic uploads.
- Everything is attributed to the app. GitHub shows
gutternote[bot]as the author; the real name is carried in the comment body and rendered by the widget. - Reads are rate limited — roughly 5k requests/hour per installation — so thread bodies are fetched on open rather than on page load.
- Threads can’t be truly deleted. GitHub’s API can’t delete an issue. Gutternote closes it; hard deletion has to happen in GitHub. If you have a data-deletion commitment, it must carve this out.
Your own endpoint
Bodies POST to an HTTPS endpoint you run, signed with HMAC-SHA256. Nothing but anchors touches Gutternote infrastructure, and unlike the GitHub backend you keep the full feature set — attachments, edits and guest authors all work if you implement them.
See the external store contract.
Or self-host the lot
If the real requirement is “none of this runs on your infrastructure”, the cleanest answer usually isn’t a storage backend — it’s running Gutternote yourself. One Go binary and a Postgres URL, in your VPC, with no product compromises at all.
Capabilities are advertised, not assumed
The widget calls /v1/config before rendering and reads the project’s capabilities, so it
hides affordances the backend can’t honour rather than failing on submit:
{ "backend": "github", "capabilities": { "attachments": false, "edit": true, "delete": true, "guestAuthors": false, "lowLatencyReads": false }}