Episode 12 of 17

Handling DELETE Requests

Implement the DELETE endpoint — find a document by ID and remove it from MongoDB, with proper error handling and response codes.

Handling DELETE Requests

The DELETE operation removes a resource from the database. In this episode you will implement the DELETE endpoint for your API using Mongoose's findByIdAndDelete() method.

The DELETE Route

// routes/ninjas.js
router.delete('/:id', async (req, res, next) => {
    try {
        const ninja = await Ninja.findByIdAndDelete(req.params.id);

        if (!ninja) {
            return res.status(404).json({ error: 'Ninja not found' });
        }

        res.json({ message: 'Ninja deleted', ninja });
    } catch (err) {
        next(err);
    }
});

How findByIdAndDelete Works

ScenarioReturn ValueStatus Code
Document found and deletedThe deleted document200 OK
Document not foundnull404 Not Found
Invalid ID formatThrows CastError400 Bad Request

findByIdAndDelete() finds a document by its _id, removes it from the collection, and returns the deleted document. If no document matches, it returns null.

Testing with Postman

DELETE http://localhost:3000/api/ninjas/65a1b2c3d4e5f6a7b8c9d0e1

Response: 200 OK
{
    "message": "Ninja deleted",
    "ninja": {
        "_id": "65a1b2c3d4e5f6a7b8c9d0e1",
        "name": "Ryu",
        "rank": 5,
        "available": true
    }
}

// Deleting again:
Response: 404 Not Found
{ "error": "Ninja not found" }

Alternative: 204 No Content

router.delete('/:id', async (req, res, next) => {
    try {
        const ninja = await Ninja.findByIdAndDelete(req.params.id);
        if (!ninja) {
            return res.status(404).json({ error: 'Ninja not found' });
        }
        res.status(204).send();  // No body in response
    } catch (err) {
        next(err);
    }
});

Some APIs return 204 No Content with an empty body after deletion. Others return 200 OK with the deleted document. Both are valid REST patterns.

Deleting Multiple Documents

// Delete all ninjas with rank less than 3
router.delete('/', async (req, res, next) => {
    try {
        const result = await Ninja.deleteMany({ rank: { $lt: 3 } });
        res.json({
            message: `Deleted ${result.deletedCount} ninjas`,
        });
    } catch (err) {
        next(err);
    }
});

Key Takeaways

  • findByIdAndDelete() finds, deletes, and returns the removed document in one operation
  • Always check if the return value is null — it means the document was not found
  • Return 200 with the deleted document or 204 with no body — both are valid
  • DELETE is idempotent — deleting a non-existent resource returns 404 every time