Search
⌘K

Implement CRUD REST APIs

Asked at:

S

Speak

Stripe

Netflix

Netflix

T

Thrive Global


DESCRIPTION

Design and implement a REST API system that supports basic CRUD operations (Create, Read, Update, Delete) with proper HTTP method handling. The system must manage stateful data storage locally and handle request/response cycles correctly. For example, a POST /users request should create a user and return the created resource with a unique ID, which can then be used in subsequent GET /users/{id} requests.

Input:

POST /users
Body: {"name": "Alice", "email": "alice@example.com"}

Output:

Status: 201 Created
Body: {"id": 1, "name": "Alice", "email": "alice@example.com"}


Explanation: Creates a new user resource and returns it with an auto-generated id

Constraints:

  • Must implement all four CRUD operations: Create (POST), Read (GET), Update (PUT), Delete (DELETE)
  • Must maintain persistent state across multiple API calls within a session
  • Must return appropriate HTTP status codes (200, 201, 204, 404, etc.)
  • Must handle resource not found scenarios gracefully
  • Must generate unique identifiers for created resources

Understanding the Problem

The core challenge is building a stateful REST API that correctly maps HTTP methods to CRUD operations while maintaining data consistency. You need to implement local data storage that persists across requests, handle request parsing to extract paths and bodies, and generate proper responses with correct status codes. The system must track resource IDs from creation through subsequent read, update, and delete operations, requiring careful state management between API calls.

Building Intuition

A naive approach might handle each request independently without persistent storage, losing data between calls. A better approach uses an in-memory data store (like a dictionary/map) to maintain state, with auto-incrementing IDs for new resources. For example, when POST /users creates user ID 1, that ID must remain valid for subsequent GET /users/1 calls until explicitly deleted.

REST APIs are the foundation of modern web services, powering everything from mobile apps to microservices. Understanding CRUD operations and stateful request handling is essential for backend development. This pattern applies to databases, caching layers, and any system that manages resources over time.

Common Pitfalls

Implementation

Data Storage Layer and ID Management

Implement the persistent storage mechanism using an in-memory data structure (dictionary) to store resources by ID. Create an ID generator that auto-increments to ensure unique identifiers for each new resource. This layer provides the foundation for all CRUD operations by maintaining state across API calls. For example, a storage dictionary maps {1: {"name": "Alice"}, 2: {"name": "Bob"}} with a next_id counter tracking the next available ID.

Solution
# Data Storage Layer and ID Management
storage = {}
next_id = 1
def get_next_id():
global next_id
current_id = next_id
next_id += 1
return current_id
def store_resource(resource_data):
resource_id = get_next_id()
storage[resource_id] = resource_data
return resource_id
def get_resource(resource_id):
return storage.get(resource_id)
def update_resource(resource_id, resource_data):
if resource_id in storage:
storage[resource_id] = resource_data
return True
return False
def delete_resource(resource_id):
if resource_id in storage:
del storage[resource_id]
return True
return False
Request Parser and Route Handler

Build a request parser that extracts the HTTP method, resource path, and resource ID from incoming requests. Implement route matching logic to determine which CRUD operation to execute based on the method and path pattern (e.g., /users vs /users/{id}). This component translates raw HTTP requests into structured data that the CRUD operations can process. For example, parse GET /users/5 into {method: "GET", resource: "users", id: 5}.

Solution
import re
def parse_request(request_string):
parts = request_string.strip().split()
method = parts[0]
path = parts[1]
match = re.match(r'^/(\w+)(?:/(\d+))?$', path)
if match:
resource = match.group(1)
resource_id = int(match.group(2)) if match.group(2) else None
return {'method': method, 'resource': resource, 'id': resource_id}
return None
def route_request(parsed_request):
method = parsed_request['method']
resource_id = parsed_request['id']
if method == 'POST' and resource_id is None:
return 'create'
elif method == 'GET' and resource_id:
return 'read'
elif method == 'PUT' and resource_id:
return 'update'
elif method == 'DELETE' and resource_id:
return 'delete'
return None
CRUD Operation Handlers

Implement the four CRUD operation functions that interact with the storage layer from Section 1. Create adds new resources with auto-generated IDs, Read retrieves resources by ID, Update modifies existing resources, and Delete removes resources. Each handler returns appropriate HTTP status codes and response bodies. For example, the update handler checks if the ID exists in storage, modifies the entry, and returns 200 with the updated resource or 404 if not found.

Solution
def handle_create(resource_data):
resource_id = store_resource(resource_data)
return {'status': 201, 'body': {'id': resource_id, 'data': resource_data}}
def handle_read(resource_id):
resource = get_resource(resource_id)
if resource:
return {'status': 200, 'body': {'id': resource_id, 'data': resource}}
return {'status': 404, 'body': {'error': 'Resource not found'}}
def handle_update(resource_id, resource_data):
if update_resource(resource_id, resource_data):
return {'status': 200, 'body': {'id': resource_id, 'data': resource_data}}
return {'status': 404, 'body': {'error': 'Resource not found'}}
def handle_delete(resource_id):
if delete_resource(resource_id):
return {'status': 200, 'body': {'message': 'Resource deleted'}}
return {'status': 404, 'body': {'error': 'Resource not found'}}
Complete API Integration

Combine the storage layer (Section 1), request parser (Section 2), and CRUD handlers (Section 3) into a unified API dispatcher. Create a main handler function that receives raw requests, parses them, routes to the appropriate CRUD operation, and formats responses with proper status codes and bodies. This integration demonstrates the full request-response cycle. For example, the dispatcher receives POST /users {"name": "Alice"}, routes to the create handler, stores the resource, and returns 201 Created with the new resource including its generated ID.

Solution
import json
def api_dispatcher(request_string, body_data=None):
parsed = parse_request(request_string)
if not parsed:
return {'status': 400, 'body': {'error': 'Invalid request'}}
operation = route_request(parsed)
if not operation:
return {'status': 405, 'body': {'error': 'Method not allowed'}}
resource_id = parsed['id']
if operation == 'create':
return handle_create(body_data)
elif operation == 'read':
return handle_read(resource_id)
elif operation == 'update':
return handle_update(resource_id, body_data)
elif operation == 'delete':
return handle_delete(resource_id)
return {'status': 500, 'body': {'error': 'Internal server error'}}

What We've Learned

  • Pattern: Use persistent storage (class/module-level data structures) to maintain state across API requests
  • HTTP Semantics: Map CRUD operations to correct methods - POST for create, GET for read, PUT for update, DELETE for delete
  • Status Codes: Return 201 for creation, 200 for success, 204 for deletion, 404 for not found
  • State Management: Store responses from early API calls (like generated IDs) to use in subsequent requests
  • Use Case: This pattern applies to building REST APIs, resource managers, database interfaces, and any system requiring stateful CRUD operations

Problems to Practice

Subarray Sum Equals K

medium

Prefix Sum

This problem requires maintaining state across operations using a hashmap to store prefix sums, similar to how CRUD APIs need to store and retrieve state locally. Both involve tracking data across multiple operations and using previous results for subsequent requests.

This problem uses a hashmap to track character positions and manage state dynamically, which mirrors the state management required in REST APIs. It demonstrates how to store, update, and query data efficiently using hashmaps.

Copy Graph

easy

Depth-First Search

This problem requires using a hashmap to map original nodes to their copies, demonstrating how to maintain relationships between entities during operations. This is analogous to managing resource IDs and references in REST API responses for later use in subsequent requests.

Question Timeline

See when this question was last asked and where, including any notes left by other candidates.

Late December, 2025

Disney

Senior

Early December, 2025

Netflix

Netflix

Mid-level

Consumers must be able to create, read, update and delete content. The content is meant to be versioned and each version is meant to be immutable. Deletion can happen only at the content-level. Consumers should be able to read the latest or any specific version of a content.

Late November, 2025

Netflix

Netflix

Senior

Comments

Your account is free and you can post anonymously if you choose.