Skip to content

Commit 5346013

Browse files
committed
docs: enhance postgres audit logging
1 parent bd3eb0e commit 5346013

File tree

1 file changed

+83
-9
lines changed

1 file changed

+83
-9
lines changed

content/blog/postgres-audit-logging.md

Lines changed: 83 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: Postgres Audit Loggging Guide
2+
title: Postgres Audit Logging Guide
33
author: Adela
44
updated_at: 2025/11/10 18:00:00
55
feature_image: /content/blog/postgres-audit-logging/cover.webp
@@ -92,7 +92,68 @@ This captures all DML operations (`INSERT`, `UPDATE`, `DELETE`) on the `users` t
9292

9393
For real-time change notifications, PostgreSQL offers the [tcn](https://www.postgresql.org/docs/current/tcn.html) module (Triggered Change Notification), which can be used to send `NOTIFY` events to listening clients when data changes.
9494

95-
## 3. pgAudit Extension
95+
## 3. Logical Replication Based Auditing
96+
97+
PostgreSQL's [logical replication](https://www.postgresql.org/docs/current/logical-replication.html) decodes changes from the Write-Ahead Log (WAL) and streams them in a structured format. This allows you to capture all data changes without adding triggers or modifying application code.
98+
99+
**How It Works**
100+
101+
Logical replication uses _replication slots_ and _output plugins_ (like `wal2json` or `pgoutput`) to convert WAL entries into JSON or other formats. Tools like [Debezium](https://debezium.io/) can then consume these changes and forward them to audit storage systems like Kafka, Elasticsearch, or S3.
102+
103+
**Example Setup**
104+
105+
Enable logical replication in `postgresql.conf`:
106+
107+
```ini
108+
wal_level = logical
109+
max_replication_slots = 4
110+
max_wal_senders = 4
111+
```
112+
113+
Create a replication slot:
114+
115+
```sql
116+
SELECT * FROM pg_create_logical_replication_slot('audit_slot', 'wal2json');
117+
```
118+
119+
Read changes:
120+
121+
```sql
122+
SELECT * FROM pg_logical_slot_get_changes('audit_slot', NULL, NULL);
123+
```
124+
125+
You'll receive JSON output like:
126+
127+
```json
128+
{
129+
"change": [
130+
{
131+
"kind": "update",
132+
"schema": "public",
133+
"table": "users",
134+
"columnnames": ["id", "email", "updated_at"],
135+
"columnvalues": [42, "[email protected]", "2025-11-10 10:30:00"],
136+
"oldkeys": { "keynames": ["id"], "keyvalues": [42] }
137+
}
138+
]
139+
}
140+
```
141+
142+
**Pros**
143+
144+
- Captures all data changes automatically, no per-table setup.
145+
- Minimal performance impact — reads from existing WAL infrastructure.
146+
- Works with existing tools like Debezium for streaming to external systems.
147+
- No application code changes required.
148+
149+
**Cons**
150+
151+
- Does not capture `SELECT` queries (only data modifications).
152+
- WAL retention can increase storage if replication slot falls behind.
153+
154+
This approach is ideal when you need **near-real-time change data capture (CDC)** for auditing, analytics, or event-driven architectures.
155+
156+
## 4. pgAudit Extension
96157

97158
For structured, compliance-grade audit logs, PostgreSQL’s [pgAudit](https://github.com/pgaudit/pgaudit) extension is the standard choice.
98159
It extends native logging to provide more context and granularity, especially around read/write operations.
@@ -130,35 +191,48 @@ AUDIT: SESSION,1,READ,SELECT,,,,"SELECT * FROM customers WHERE id=42;",<none>
130191
- Logs can be verbose — use `pgaudit.log_parameter = off` to reduce noise.
131192
- Requires proper log rotation and analysis strategy.
132193

133-
## 4. Bytebase
194+
## 5. Bytebase
134195

135-
Bytebase is a Database DevSecOps platform that provides a [centralized audit trail](https://docs.bytebase.com/security/audit-lo) across your PostgreSQL environments.
196+
Bytebase is a Database DevSecOps platform that provides a [centralized audit trail](https://docs.bytebase.com/security/audit-log) across your PostgreSQL environments.
136197
It records _who did what, when, and why_ — linking SQL actions to their context (issues, approvals, and deployments) while keeping sensitive data secure.
137198

138199
**What Bytebase Audits**
139200

140201
- **Query access:** logs _who queried which data_ and _when_ across SQL Editor, Admin Query, and Data Export.
141202
- **Schema and data changes:** tracks _who made which changes_, _when they were approved_, and _through which workflow or Git commit_.
142203
- **Governance controls:** built-in SQL review rules, approval flow, and role-based access help prevent unauthorized actions.
204+
- **Actual end users, not just database users:** A critical advantage is that Bytebase solves the **shared database user problem**. In most applications, all queries use the same database connection user (like `app_user`), making it impossible to trace actions back to individual users using traditional database auditing. Since users operate through Bytebase, every action is attributed to the actual end user, not just a generic database account.
143205

144206
**Why It Matters**
145207

146208
- **Complete visibility** across read and write operations.
147209
- **Privacy-safe auditing** with no sensitive data exposure.
148210
- **Compliance-ready** logs aligned with SOC 2, ISO 27001, and GDPR.
149211

150-
Unlike other solutions, which records statements at the database level, Bytebase captures **who accessed or changed data, under which approval, without exposing sensitive information**. You can also call the [API](https://docs.bytebase.com/integrations/api/audit-log) to send the audit logs to a centralized log sink.
212+
You can also call the [API](https://docs.bytebase.com/integrations/api/audit-log) to send the audit logs to a centralized log sink.
151213

152214
## Conclusion
153215

154216
PostgreSQL offers multiple layers of auditing — from basic text logs to complete governance solutions.
155217

156-
- Use **native logging** for baseline activity tracking.
218+
**Comparison Table**
219+
220+
| Approach | Performance Impact | Captures SELECTs | Captures Actor | Row-Level Detail | Best For |
221+
|----------|-------------------|------------------|----------------|------------------|----------|
222+
| **Native Logging** | Low-Medium || ⚠️ DB user only || Development, debugging, basic audit trails |
223+
| **Triggers** | Medium-High || ⚠️ DB user only | ✅ (before/after) | Critical tables needing full change history |
224+
| **Logical Replication** | Low |||| Real-time CDC, event-driven systems, analytics |
225+
| **pgAudit** | Medium || ⚠️ DB user only || Compliance requirements, structured logging |
226+
| **Bytebase** | N/A (app-level) || ✅ End user || Centralized governance, approval workflows, team collaboration |
227+
228+
- Use **native logging** for baseline activity tracking (captures database user only).
229+
230+
- Use **triggers** for fine-grained row-level auditing on critical tables (captures database user only).
157231

158-
- Use **pgAudit** for structured, compliance-grade statement logging.
232+
- Use **logical replication** for near-real-time change data capture without application changes.
159233

160-
- Add **Bytebase** for centralized auditing that records who accessed or changed data, when, and why — all while protecting sensitive information.
234+
- Use **pgAudit** for structured, compliance-grade statement logging (captures database user only).
161235

162-
- Optionally, use **triggers** for fine-grained row-level auditing on critical tables.
236+
- Add **Bytebase** for centralized auditing that tracks actual end users (not just database users), linking every action to the person who performed it with full context of approvals and workflows.
163237

164238
By combining these layers, you gain both the visibility and control needed for secure, compliant, and well-governed database operations.

0 commit comments

Comments
 (0)