
Why Some APIs Should Be Append-Only
Most backend applications follow the traditional CRUD model:
- Create
- Read
- Update
- Delete
This approach works perfectly for many types of data. Users update their profiles, products change prices, and tasks are deleted after they're completed.
However, not every piece of data should be editable.
Some information represents history, and history should never be rewritten.
Examples include:
- Audit logs
- Payment transactions
- Login history
- Security events
- Order status history
- Permission changes
- Financial records
For these cases, an append-only API is often a much better design.
What Does Append-Only Mean?
An append-only system allows new records to be created, but existing records can never be modified or deleted.
Instead of changing history, you simply add another event.
Imagine a user's role changes from USER to ADMIN.
A traditional database might only store the latest value:
Role = ADMIN
But several important questions remain unanswered:
- Who changed the role?
- When did it happen?
- What was the previous value?
- Which administrator performed the action?
- From which IP address?
An append-only system stores every change as a separate event.
Actor: admin-42
Action: ROLE_CHANGED
Target User: user-17
Old Role: USER
New Role: ADMIN
Timestamp: 2026-07-24T10:30:00Z
If the role changes again tomorrow, the previous record remains untouched.
A new event is simply appended.
Why Prevent UPDATE and DELETE?
The primary purpose of an audit log is to preserve the truth.
If someone can modify or delete historical records, the system loses credibility.
Imagine an administrator executing:
DELETE FROM audit_events
WHERE actor_id = 42;
Every trace of their actions disappears.
Or even worse:
UPDATE audit_events
SET action = 'PROFILE_VIEWED'
WHERE action = 'ROLE_GRANTED';
The event still exists, but it no longer reflects reality.
This is why append-only APIs follow a simple rule:
INSERT ✅
SELECT ✅
UPDATE ❌
DELETE ❌
History should be preserved, not rewritten

Designing an Append-Only API
A simple Audit Event entity might look like this:
@Entity
public class AuditEvent {
@Id
private Long id;
private Long actorId;
private String action;
private String resourceType;
private String resourceId;
private String ipAddress;
private Instant occurredAt;
}
The service only exposes creation and read operations.
public AuditEvent create(AuditEvent event);
public Page<AuditEvent> findAll(Pageable pageable);
Notice what's missing.
update()
delete()
deleteById()
These operations simply do not exist.
Likewise, the REST API exposes only:
POST /audit-events
GET /audit-events
GET /audit-events/{id}
There are intentionally no endpoints for:
PUT
PATCH
DELETE
The API itself communicates that audit history is immutable.
Application-Level Protection Isn't Enough
Removing update endpoints is a good start.
But what if someone connects directly to the database?
Or another service accidentally executes an UPDATE statement?
Business rules that are truly critical should not rely only on application code.
They should also be enforced by the database itself.
Enforcing Append-Only in PostgreSQL
A PostgreSQL trigger can reject every UPDATE and DELETE automatically.
CREATE OR REPLACE FUNCTION reject_audit_event_mutation()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
RAISE EXCEPTION 'audit_events is append-only';
END;
$$;
Then attach the trigger.
CREATE TRIGGER audit_events_append_only
BEFORE UPDATE OR DELETE
ON audit_events
FOR EACH STATEMENT
EXECUTE FUNCTION reject_audit_event_mutation();
Now any attempt to modify history fails immediately.
DELETE FROM audit_events;
Result:
ERROR:
audit_events is append-only
The database itself becomes the final guardian of your business rule.

How Do You Correct Mistakes?
One common question is:
"What if someone inserts incorrect data?"
You don't modify the existing record.
Instead, you append another event that corrects the previous one.
Example:
PAYMENT_CREDITED +100 USD
Correction:
PAYMENT_REVERSAL -100 USD
Both events remain in history.
Nothing disappears.
This creates a complete and trustworthy audit trail.
Advantages of Append-Only APIs
Complete History
Every event remains available for investigation.
Better Security
Critical actions cannot be hidden.
Regulatory Compliance
Many industries require immutable records for legal reasons.
Easier Auditing
Security teams can reconstruct exactly what happened.
Higher Trust
The system never rewrites historical events.
Challenges
Append-only isn't free.
As data grows, storage requirements increase.
Common solutions include:
- Table partitioning
- Data archiving
- Cold storage
- Retention policies
- Compression
Another challenge is determining the current state.
Sometimes the latest value must be reconstructed from multiple events.
For example:
ORDER_CREATED
ORDER_PAID
ORDER_SHIPPED
ORDER_DELIVERED
Many systems solve this by maintaining two models:
- A current-state table
- An append-only event history
This combines fast queries with complete traceability.
Should Every API Be Append-Only?
Definitely not.
User profiles should be editable.
Products need price updates.
Tasks should be marked as completed.
CRUD remains the correct choice for many business domains.
Append-only is most valuable when answering one question matters:
"What exactly happened in the past?"
If preserving that history is essential, append-only is likely the better design.
Final Thoughts
Append-only APIs are more than just a database pattern.
They are a design philosophy centered around trust, traceability, and data integrity.
Whenever your system handles:
- Audit logs
- Financial transactions
- Security events
- Permission changes
- Order history
- Event-driven workflows
consider whether your data should be updated or simply grow over time.
Sometimes the most reliable system isn't the one that edits history.
It's the one that never allows history to change.
If you enjoy backend engineering content covering Java, Spring Boot, System Design, Distributed Systems, and Software Architecture, feel free to connect with me here on LinkedIn.
📸 Instagram: @the.code.architect — Short visual explanations and engineering diagrams.
✍️ Medium: Long-form deep dives into backend architecture, performance, and system design.
Question for you: Have you ever designed an append-only system? If so, what business problem did it solve?
Comments (0)
Loading comments...