AuditRailsAuditRails

Security

You shouldn't have to take our word for it. This page explains exactly how AuditRails protects your data, and how to verify our core claim yourself.

Threat model

Every claim on this page is only useful if you also know its edges. Here's what AuditRails is built to defend against, and what it explicitly isn't.

What we defend against

Tampering with a logged event after the fact: any edit to a stored event breaks the hash chain from that point forward, and our open-source verifier can prove it independently, without trusting our infrastructure. Deletion or early expiry of audit data. S3 Object Lock in Compliance mode blocks that for everyone, including us. One tenant reading another tenant's data, every query, storage path, and cache key is scoped to a tenant at the query layer itself.

What we don't defend against

We hash-chain events; we don't sign them with per-customer asymmetric keys, so there's no signing-key infrastructure to manage or rotate, by design. A compromised API key is scoped to that one tenant's data, it can't reach anyone else's, but it can act within its own tenant until revoked. And we don't run a dedicated WAF or L7 filtering layer in front of our infrastructure; we rely on Hetzner's built-in network-edge DDoS mitigation plus our own per-tenant rate limiting.

Architecture

Your SDK sends events to our Go ingestion API, which authenticates the request and publishes it to a queue (AWS SQS). A processing worker reads the queue, computes the cryptographic hash chain, and writes to three places: S3 (Object Lock, the durable source of truth), ClickHouse (a 90-day hot query cache), and Cassandra (an unbounded cold store backing exports and reports beyond ClickHouse's window). The dashboard reads from these stores, never directly from your application.

SDK

Node, Python, Go, PHP

Ingestion API

Validates, enriches, queues

Hash Chain + WORM

S3 Object Lock, ClickHouse, Cassandra

Dashboard

Search, verify, export, comply

Encryption

In transit

All public traffic, the SDK, the dashboard, and this website, is served over TLS with automatically renewed certificates. There is no unencrypted path from your SDK to our ingestion API.

At rest

Your audit logs' durable copy in S3 is encrypted at rest with AWS KMS (SSE-KMS).

Work in progress

Our self-hosted database layer (PostgreSQL, ClickHouse, Cassandra, Redis) does not yet have disk-level encryption configured. That work is in progress, and we would rather tell you here, plainly, than let you find it in due diligence.

Immutable storage (WORM)

Audit logs are written to S3 with Object Lock in Compliance mode, not Governance mode. That distinction matters: in Compliance mode, no one, including AuditRails administrators and AWS' own root account, can shorten a retention lock or delete a log before it expires. The default retention window is seven years.

WrittenLocked (COMPLIANCE mode)6 months – 10 years

No one, including AuditRails admins, can shorten, edit, or delete a locked object before its retention window ends.

Verify it yourself

We publish an open-source command-line tool that independently recomputes your audit log's hash chain and confirms it hasn't been tampered with. It doesn't call our API and doesn't trust our infrastructure, it only trusts the math.

View the verifier on GitHub →

Key and secrets handling

API keys

We never store your API keys in plaintext. Only a SHA-256 hash is persisted; the raw key is shown to you exactly once, at creation.

Infrastructure secrets

Database credentials, payment provider keys, and other infrastructure secrets are encrypted at rest with age/sops, and decrypted only into ephemeral, memory-backed storage at deploy time, never written to persistent disk in plaintext.

Multi-tenancy isolation

Every API key maps to exactly one tenant. Every database query, every S3 path, and every cache key enforces tenant isolation at the query layer itself, not as an application-level convention. There is no code path that can return one organization's data to another.

Tenant A

isolated

Tenant B

isolated

Tenant C

isolated

Our own compliance posture

We're actively preparing for a SOC 2 Type II audit. We haven't started the formal audit process yet, and we'd rather say that plainly than leave you guessing.

Subprocessors

Third-party infrastructure and services we rely on:

AWS

Amazon Web Services, S3 (WORM audit log storage) and SQS (queueing) only.

Hetzner

Hetzner, hosting for our application servers and databases.

Stripe

Stripe, payment processing.

Resend

Resend, transactional email.

Sentry

Sentry, error tracking.

Plausible

Plausible, cookieless website analytics on this site only.

MaxMind

MaxMind, geo-IP enrichment for logged events.

Cloudflare Turnstile

Cloudflare Turnstile, bot protection on our public contact and registration forms.

Let's Encrypt

Let's Encrypt, TLS certificates.

Download our security questionnaire (CAIQ-lite) →

Report a vulnerability

If you find a security vulnerability, please report it to us responsibly rather than opening a public GitHub issue.

security@auditrails.io

We acknowledge every report within 24 hours. For critical vulnerabilities (CVSS 9.0+), we aim to respond within 4 hours and ship a fix within 24 hours.

This covers the AuditRails dashboard, ingestion API, processing worker, all official SDKs, and our infrastructure configuration.

This address is for reporting vulnerabilities in our own systems. If you're a customer asking about our personal-data breach notification commitment (48 hours), that's defined in our DPA.

Read our full disclosure policy

Backups and recovery

We run nightly backups of PostgreSQL and Cassandra to a separate, dedicated storage location. Restore isn't just scripted, it's tested: our most recent drill (2026-08-25) restored both databases from backup and confirmed an exact row-count match against live data.