CRUD Operations: Create, Read, Update, Delete Explained
CRUD = Create, Read, Update, Delete — the four basic data operations. Maps to SQL INSERT/SELECT/UPDATE/DELETE and HTTP POST/GET/PUT/DELETE.
What is CRUD?
CRUD stands for Create, Read, Update, Delete — the four fundamental operations performed on persistent data. Almost every database, API, and app boils down to these four verbs. Understanding CRUD is foundational because:
- Database systems implement CRUD as SQL statements (INSERT, SELECT, UPDATE, DELETE).
- REST APIs map CRUD onto HTTP methods (POST, GET, PUT/PATCH, DELETE).
- UI frameworks scaffold CRUD interfaces automatically (Rails, Django admin, etc.).
- Testing CRUD coverage gives a baseline for any data-driven app.
The four CRUD operations
| Operation | Purpose | SQL | HTTP |
|---|---|---|---|
| Create | Add new record | INSERT | POST |
| Read | Retrieve record(s) | SELECT | GET |
| Update | Modify existing record | UPDATE | PUT / PATCH |
| Delete | Remove record | DELETE | DELETE |
CRUD in SQL
-- Create
INSERT INTO users (email, name) VALUES ('alice@example.com', 'Alice');
-- Read
SELECT * FROM users WHERE id = 42;
-- Update
UPDATE users SET name = 'Alice Smith' WHERE id = 42;
-- Delete
DELETE FROM users WHERE id = 42;CRUD in REST APIs
# Create
POST /users
Content-Type: application/json
{ "email": "alice@example.com", "name": "Alice" }
→ 201 Created, Location: /users/42
# Read (one)
GET /users/42
→ 200 OK, { "id": 42, "email": "...", ... }
# Read (many)
GET /users?limit=20&offset=0
→ 200 OK, [ {...}, {...} ]
# Update (full replace)
PUT /users/42
{ "email": "alice@example.com", "name": "Alice Smith" }
→ 200 OK
# Update (partial)
PATCH /users/42
{ "name": "Alice Smith" }
→ 200 OK
# Delete
DELETE /users/42
→ 204 No ContentPUT vs PATCH
| Method | Behavior | Use case |
|---|---|---|
| PUT | Replace entire resource | Caller sends full new state |
| PATCH | Apply partial changes | Caller sends only changed fields |
PATCH is preferred for typical edit forms (sending a small diff). PUT is for full-replacement workflows (and is idempotent by definition).
HTTP status codes for CRUD
| Operation | Success status | Common errors |
|---|---|---|
| Create | 201 Created | 400, 409, 422 |
| Read | 200 OK | 404 |
| Update | 200 OK or 204 No Content | 400, 404, 409, 422 |
| Delete | 204 No Content | 404, 409 |
CRUD beyond REST
GraphQL
Single endpoint; CRUD via queries (read) and mutations (create/update/delete).
mutation { createUser(input: {...}) { id name } }
query { user(id: 42) { id name } }
mutation { updateUser(id: 42, input: {...}) { id name } }
mutation { deleteUser(id: 42) { success } }gRPC
RPC methods named for the operation: CreateUser, GetUser, UpdateUser, DeleteUser.
Event-sourced systems
CRUD ops become events: UserCreated, UserUpdated, UserDeleted. State derived from event log.
CRUD best practices
- Validate at every layer. Client + API + database. Defense in depth.
- Soft delete vs hard delete. Soft delete (set
deleted_at) preserves history; hard delete reclaims space. - Auth on every operation. Read isn't free — leaking data is a breach.
- Audit log. Who created/updated/deleted what, when. Critical for compliance.
- Optimistic concurrency. Use ETag or version field to prevent lost updates.
- Rate limit writes. Reads are usually cacheable; writes hit the DB.
- Pagination on list reads. Always. Never
SELECT * FROM userswithout limit. - Bulk operations. For 1000 inserts, use bulk INSERT — single transaction.
- Idempotency keys. Especially for Create — prevent duplicate from retried requests.
Common CRUD pitfalls
- N+1 queries on read. List endpoint that runs a query per record. Use eager loading / JOINs.
- No pagination. List endpoint returns 1M records; client crashes.
- Lost updates. Two clients update same record; one's change overwritten. Use ETag/version.
- Cascade delete surprise. Deleting user wipes all their orders silently.
- SQL injection in CRUD. Build queries from user input without parameterization.
- Missing 404 on read. Return 200 with null instead of 404 for not-found.
- PUT replacing partial fields. Caller sends
{name: "x"}, server replaces entire user — clears email, etc.
FAQ: CRUD operations
Is every API CRUD?
Most data APIs map cleanly to CRUD. APIs that do business logic (transfer money, send email, run a job) often have non-CRUD verbs (e.g., POST /transfers, POST /users/42/send-welcome-email).
What about PATCH?
PATCH is part of the RESTful CRUD vocabulary, paired with (or replacing) PUT for partial updates. Some APIs use only PATCH; others use PUT for replace + PATCH for partial.
Should I soft-delete or hard-delete?
Soft-delete by default (preserves history, reversible). Hard-delete for compliance (GDPR right-to-erasure) or storage reclamation.
What's idempotency in CRUD?
Same request produces same result. GET, PUT, DELETE are idempotent. POST is not (each call creates a new resource). Use idempotency keys to make POST safe to retry.
How do I prevent lost updates?
Optimistic concurrency: client sends ETag or version; server rejects if changed since.
What's the difference between CRUD and REST?
CRUD = the operations themselves. REST = an architectural style for APIs that often (but not always) maps to CRUD over HTTP.
Should every model have full CRUD?
Not necessarily. Read-only models are fine (no Create/Update/Delete endpoints). Append-only models are fine. Match the API to the actual use case.
Load test your CRUD API with LoadFocus
LoadFocus runs JMeter and k6 scripts that exercise create/read/update/delete flows under load from 25+ regions, surfacing bottlenecks like N+1 queries and lost updates. Sign up free at loadfocus.com/signup.
Related LoadFocus Tools
Put this concept into practice with LoadFocus — the same platform that powers everything you just read about.