Welcome back! In the last lesson, we mastered the "Update" part of CRUD, implementing a PATCH endpoint to modify existing records. With create, read, and update operations in place, our API is almost complete.
This lesson focuses on the final piece of the puzzle: D for Delete. You will learn how to implement an endpoint that permanently removes a record from the database. This is the last fundamental operation needed to give you full control over your data via the API.
We will cover the standard HTTP DELETE method, the correct status code to return for a successful deletion, and how to write the corresponding FastAPI path operation to interact with your SQLAlchemy database.
The DELETE Operation
The DELETE method is straightforward: its purpose is to delete a specific resource. Just like our GET (single item) and PATCH endpoints, a DELETE request typically identifies the resource to be removed using a path parameter, such as an ID.
The logical flow for a delete operation is simple and should feel familiar:
- Receive a request to a path like
/items/{item_id}. - Find the item in the database with that ID.
- If the item doesn't exist, return a
404 Not Founderror. - If it does exist, remove it from the database.
- Signal that the deletion was successful.
The 204 No Content Status Code
A key convention in REST API design relates to the response from a DELETE request. Since the resource has been removed, there's nothing to send back in the response body.
The standard way to signal a successful deletion is with the HTTP status code 204 No Content. This code tells the client, "I did what you asked, and it was successful, but I have no data to give you in return."
FastAPI makes it easy to set this as the default status code for an endpoint.
Implementing the DELETE Endpoint
Let's translate this logic into code. The implementation is very similar to the start of our update_item function, but it ends with a deletion instead of an update.
The following video from Corey Schafer, which you've seen before, provides a concise walkthrough of creating a DELETE endpoint.
Python FastAPI Tutorial (Part 6): Completing CRUD - Update and Delete (PUT, PATCH, DELETE)
Watch this clip to see how to implement a DELETE path operation in FastAPI, including setting the status code to 204 No Content.
Watch from 15:57 to 18:55. Pay attention to the @app.delete decorator, the check for a 404 error, and how the db.delete() and db.commit() calls work together.
Now, let's add the DELETE endpoint to your main.py file. The code follows the exact pattern shown in the video.
# In main.py
# ... other imports
from fastapi import status # Import the status module
# ... your app setup and other endpoints ...
@app.delete("/items/{item_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(item_id: int, db: AsyncSession = Depends(get_db)):
# 1. Get the existing item from the database
db_item = await db.get(models.Item, item_id)
if not db_item:
raise HTTPException(status_code=404, detail="Item not found")
# 2. Delete the item from the session
await db.delete(db_item)
# 3. Commit the transaction to the database
await db.commit()
# 4. No response body is returned due to the 204 status code
return
Let's break down the key parts of this code:
@app.delete("/items/{item_id}", ...): We use the@app.deletedecorator to register this function to handleDELETErequests to the specified path.status_code=status.HTTP_204_NO_CONTENT: This is how you tell FastAPI that the default response for a successful request should be204. You importstatusfromfastapito get access to a full list of HTTP status codes.await db.get(...)andHTTPException: This is the same logic we used in the update and retrieve endpoints to find the record or return a404error if it's missing.await db.delete(db_item): This is the core SQLAlchemy async command. It stages thedb_itemobject for deletion within the current database session. The record isn't actually deleted from the database yet.await db.commit(): This command finalizes the transaction, permanently deleting the record from the database table.return: Because we've set the status code to204, FastAPI knows not to expect a response body. A simplereturnor returningNoneis sufficient. You don't need aresponse_modelhere.
For another perspective, this article from the official SQLModel tutorial shows the exact same logic in a synchronous context.
Delete Data with FastAPI - SQLModel
This page from the SQLModel documentation provides a clear, textual explanation of the delete operation.
Read the section "Delete Path Operation". Notice that the core logic—find the object, delete it from the session, then commit—is identical. This example returns a JSON object {"ok": True} with a default 200 OK status, which is an alternative to 204 No Content. Both are valid, but 204 is more common for DELETE.
Testing Your DELETE Endpoint
Now that you've added the code, it's time to test it and see it in action.
- Make sure your Uvicorn server is running.
- Open your browser to
http://127.0.0.1:8000/docs. - First, use the
POST /items/endpoint to create a new item. Note its ID. - (Optional) Use the
GET /items/{item_id}endpoint with the new ID to confirm it was created successfully. - Now, expand the
DELETE /items/{item_id}endpoint. - Click "Try it out", enter the ID of the item you just created, and click "Execute".
You should see a 204 response code and "No content" in the response body section.

To be absolutely sure, try using the GET /items/{item_id} endpoint again with the same ID. This time, you should receive a 404 Not Found error, proving the record is gone.
Beyond Simple Deletion: Soft Deletes
In many real-world applications, especially those where data integrity and history are important, records are rarely deleted permanently from the database. Instead, a "soft delete" is performed.
A soft delete typically involves marking a record as inactive rather than removing it. This is often done by setting an is_deleted boolean flag to True or populating a deleted_at timestamp. Your API's "read" queries would then be updated to filter out these "deleted" records.
This approach has several advantages:
- Data Recovery: You can easily "undelete" a record.
- Auditing: You maintain a full history of all data, which can be crucial for compliance and analytics.
- Referential Integrity: Other records that point to the "deleted" record don't break.
You don't need to implement this now, but it's an important concept to be aware of as you build more complex, production-ready systems. The fastapitutorial.com blog provides a good, brief explanation of this concept. You can find it under the "Alternative Approaches" section in the article "Delete a Model Object using SQLModel" (ID: [LINK](https://fastapitutorial.com/blog/delete-model-object-sqlmodel-fastapi/)).
Conclusion
Excellent work! You have now implemented all four CRUD operations—Create, Read, Update, and Delete. You have a complete, functioning REST API for managing a resource in your database. This is a foundational skill for any backend developer.
Key Takeaways:
- The HTTP
DELETEmethod is used to remove a resource. - The standard success response for a
DELETEoperation is204 No Content, indicating success without a response body. - You can set the status code in FastAPI with the
status_codeargument in the decorator (e.g.,@app.delete(..., status_code=status.HTTP_204_NO_CONTENT)). - The database logic involves fetching the record, calling
db.delete()on it, and then callingdb.commit()to finalize the deletion. - "Soft deletes" are a common pattern in production applications to preserve data history and allow for recovery.
In the next lesson, we will address a small but important security detail: how to prevent sensitive information, such as user passwords or internal flags, from being accidentally exposed in your API responses using response_model_exclude.