When I hear someone say “we’re about to create new service X,” it’s often followed by: “it’ll use a simple CRUD interface for the V0.” While this design approach appealed to me once upon a time, increasingly I’ve started to feel like it’s not the best design fit. In this post, I talk through some real-world issues I’ve run into using CRUD and how they might change our approach to good API design.
As a refresher, the term CRUD stands for Create, Read, Update, Delete, and it attempts to describe the “four basic operations of persistent storage.” The term originates from early work with relational databases. It maps very closely with the INSERT, SELECT, UPDATE, and DELETE operations of standard SQL; and since it looks a lot like the HTTP verbs CREATE, GET, POST, and DELETE, its use is also widespread in web and library API design. CRUD feels very intuitive for any resource-centric workflow — you would first “create” it, after which could you can “read” its current value, “update” it to a new one, or “delete” it.
While CRUD at first glance seems pretty easy to understand, implement, and use, I find it far less appealing in practice. To explain what I mean, let’s take a look at CRUD’s individual functions: