UseBetter Audit
UseBetter Audit is an open-source library that adds compliance-ready audit logging to your TypeScript application without touching your business logic. It intercepts every INSERT, UPDATE, and DELETE through your ORM, tags each entry with the current actor, and stores everything in your own database — no external service, no per-event pricing, no data leaving your infrastructure.
Key features
Section titled “Key features”- ORM auto-capture — a transparent proxy (Drizzle) or extension (Prisma) intercepts every mutation. No
captureLog()calls scattered through your code. - Actor tracking — framework middleware extracts the current user from each request (JWT, header, or cookie) and stores it in
AsyncLocalStorage. Every audit entry is tagged automatically, with no explicit passing required. By default, if extraction fails the request proceeds without an actor — switch to fail-closed viaonErrorif attribution is mandatory for your compliance requirements. - Before/after snapshots — each entry records the full record state before and after the mutation as typed
beforeDataandafterDatasnapshots. - Enrichment — attach human-readable labels, severity levels, and dynamic descriptions to specific operations. Configured once, applied everywhere.
- Compliance-ready — tag operations with
gdpr,soc2,hipaa, and other compliance frameworks. Redact sensitive columns from snapshots on a per-table basis. - Your own database — audit logs are stored in an
audit_logstable alongside your application data. Postgres, MySQL, and SQLite are all supported. - Queryable history — filter by actor, resource, operation, or time range via
audit.query()or the CLI. - Plugin-driven — extend with custom enrichers, exporters, and retention policies.
How it works
Section titled “How it works”- A request arrives. Framework middleware (Hono, Express, or Next.js) extracts the actor ID from the
Authorizationheader or a custom source and stores it inAsyncLocalStorage. - Your handler runs a mutation —
db.insert(users).values(...)orprisma.user.create(...)— against the audited client. - The ORM proxy or extension intercepts the mutation, reads the actor from
AsyncLocalStorage, captures before/after state, and writes a typed entry toaudit_logs. - Audit entries are queryable immediately via
audit.query()or the audit CLI export command.
Because capture happens at the ORM layer, not the HTTP layer, it works in background jobs and cron tasks too — just set the actor explicitly with setAuditContext().
Library, not a service
Section titled “Library, not a service”Most audit logging solutions are SaaS products: you send events to their API, pay per event, and your data lives on their servers. UseBetter Audit is a library:
- No external API calls — mutations are captured in-process and written directly to your database.
- No vendor lock-in — your audit data is in a plain SQL table you own. Query it with any tool.
- No per-event pricing — capture as much as you want; your only cost is storage.
- No schema surprises — the
audit_logstable is generated by the CLI and lives in your migrations. You can inspect and extend it.
Architecture
Section titled “Architecture”| Layer | Package | Role |
|---|---|---|
| Core | @usebetterdev/audit-core | Event model, adapter contract, enrichment config, query API. Zero runtime deps. |
| ORM adapters | @usebetterdev/audit-drizzle, @usebetterdev/audit-prisma | Intercept mutations, write audit_logs, expose the auditLogs table schema. |
| Framework adapters | audit-hono, audit-express, audit-next | Middleware that extracts the actor per request and stores it in context. |
| CLI | @usebetterdev/audit-cli | Migrations, health check, stats, export, purge. |
| Umbrella | @usebetterdev/audit | Single install, subpath exports for all adapters. |
You install the umbrella package (@usebetterdev/audit) and import adapters via subpath exports like @usebetterdev/audit/drizzle and @usebetterdev/audit/hono.
Next steps
Section titled “Next steps”- Installation — install the package and its peer dependencies
- Quick Start — wire up audit logging in your app in minutes
- Configuration — core options, enrichment, retention, and hooks
- Actor Context — automatic actor propagation via AsyncLocalStorage
- Enrichment — human-readable labels, severity, compliance tags, and redaction
- Compliance Overview — map SOC 2, HIPAA, GDPR, and PCI DSS requirements to Better Audit features
- Adapters — per-adapter setup for Drizzle, Prisma, Hono, Express, and Next.js
- How Audit Works — interactive walkthrough of the three-layer pipeline