Implementing Audit Logging

1. Adding Created Timestamp

FieldDetail
createdAt: DateTime!Set on insert; immutable
DB defaultDEFAULT now() or trigger

2. Adding Updated Timestamp

FieldDetail
updatedAt: DateTime!Set on every update
ORM hooksPrisma @updatedAt, TypeORM @UpdateDateColumn

3. Adding Created By Field

Example: Created/updated by

type Post {
  createdAt: DateTime!
  updatedAt: DateTime!
  createdBy: User!
  updatedBy: User
}

4. Adding Updated By Field

SourceDetail
Context userSet in resolver from ctx.user.id
DB session varPostgres SET LOCAL app.user_id = ...
ORM middlewareAuto-fill on save

5. Logging Field Changes

Example: Diff before/after

const before = await db.post.findUnique({ where: { id } });
const after = await db.post.update({ where: { id }, data: input });
const diff = computeDiff(before, after);
await db.auditLog.create({
  data: { entity: "Post", entityId: id, actor: ctx.user.id, op: "UPDATE", diff }
});

6. Implementing Audit Trail

ColumnUse
id, occurredAt, actorWho, when
entity, entityIdWhat was changed
operationCREATE, UPDATE, DELETE, READ
before, afterJSON snapshots
requestId, ip, userAgentRequest context

7. Storing Change Metadata

StorageUse
Same DB, separate tableSimple, transactional
Append-only logKafka, S3 — immutable
Time-series DBClickhouse, TimescaleDB

8. Querying Audit Logs

Example: Audit log query

type Query {
  auditLog(
    entity: String
    entityId: ID
    actor: ID
    dateRange: DateFilter
    first: Int = 50
    after: String
  ): AuditLogConnection!
}

9. Implementing Version History

PatternDetail
Version tableEach row is a snapshot
BitemporalTrack validFrom/validTo + transactionTime
Diff-onlyStore JSON-Patch per change

10. Using Event Sourcing

ConceptDetail
EventsSource of truth: PostCreated, PostEdited
ProjectionsRead models built by replaying events
CQRSMutations write events; queries read projections
Trade-offHigher complexity; great for audit + replay