Implement CRUD REST APIs
Asked at:
Speak
Netflix
Stripe
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.
# Data Storage Layer and ID Managementstorage = {}next_id = 1def get_next_id():global next_idcurrent_id = next_idnext_id += 1return current_iddef store_resource(resource_data):resource_id = get_next_id()storage[resource_id] = resource_datareturn resource_iddef 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_datareturn Truereturn Falsedef delete_resource(resource_id):if resource_id in storage:del storage[resource_id]return Truereturn 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}.
import redef 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 Nonereturn {'method': method, 'resource': resource, 'id': resource_id}return Nonedef 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.
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.
import jsondef 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
medium
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.
medium
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.
easy
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
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
Senior
Comments
Hello Interview Premium
Your account is free and you can post anonymously if you choose.