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.
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.
Report a vulnerability
If you find a security vulnerability, please report it to us responsibly rather than opening a public GitHub issue.
security@auditrails.ioWe 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.
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.