“We already have logs” does not answer a question about auditing business operations.
Technical logs help explain why a request failed, how long a query took or where an integration timed out. An audit log answers different questions: who made a decision, in which organization, what changed and which process caused it.
This is not a naming difference. It is a difference in guarantees.
Three kinds of history
A mature system should distinguish:
- technical telemetry - exceptions, latency, retries and infrastructure state;
- product activity - user-facing history such as comments or workflow progress;
- authoritative audit - evidence of decisions, permission changes and critical operations.
One event may have representations in more than one place, but each record serves a different purpose. An activity feed can optimize for UX. Audit evidence must preserve integrity and unambiguous provenance.
One operation, one transaction
In a critical process, the business state and its audit event should be written in the same primary-database transaction.
Validate business command
↓
Change business state
↓
Record audit event
↓
Commit one transaction
If the event cannot be stored, the change does not commit. A queue backed by another database may later export the event to a SIEM or WORM store, but it should not be the only place where authoritative evidence is created.
The event contract
A useful event has:
- a stable type and schema version,
- a public unique identifier,
- an organization or explicit platform scope,
- actor kind and identifier,
- invocation source,
- subject and optional business context,
- correlation ID and optional cause,
- constrained metadata,
- occurrence and persistence timestamps.
Arbitrary JSON is not a contract. Define allowed keys, required values, size limits and a version for every event type. Consumers then know what they receive, and an accidental request parameter cannot enter permanent history.
Passwords, tokens, session identifiers, full documents, prompts and personal data without a defined purpose do not belong in audit metadata. Integrity starts with minimization.
Protection below Rails
A model-level readonly? guard protects against an application mistake, not direct SQL. If runtime owns the table or runs as a superuser, it can alter records or disable protection.
A stronger boundary separates the object owner, migrator and runtime identities. The application process receives only the read and append privileges it needs. Updates, deletes and TRUNCATE are blocked through both ACLs and owner-controlled triggers.
This still cannot protect against the administrator of the entire database or host. Detecting that level of interference needs an independent trust boundary: signed checkpoints or export to a separately administered append-only destination.
Audit does not create compliance automatically
Technology can provide integrity, traceability and access control. Compliance also needs a processing purpose, retention schedule, legal hold, emergency procedures, reader authorization and regular restore testing.
The core distinction remains simple: technical logs describe system behavior. Audit logs document responsibility for business events.
Read more about our production technology standards and modernization and infrastructure work. If you need to restructure audit evidence in an existing system, start a conversation.

