In this tutorial, we will build a CRUD API for a feedback application. This project will help you get started with API development in Rust or enhance your skills as a Rust developer.
We’ll begin by setting up the Rust project with Cargo, then launch an SQL database server using Docker. After that, we’ll perform database migrations to create the necessary records for the feedback app. Next, we will build HTTP routes to handle CRUD requests sent to the server.
This is just an overview of the steps we’ll take to build the feedback API. As we progress, we’ll incorporate additional steps to guide us toward the final result. So, get ready, and let’s dive in!
Related Articles
- Building a Rust API with Unit Testing in Mind
- How to Write Unit Tests for Your Rust API
- How to Add Swagger UI, Redoc and RapiDoc to a Rust API
- JWT Authentication and Authorization in a Rust API using Actix-Web
- How to Write Unit Tests for Your Rust API
- Dockerizing a Rust API Project: SQL Database and pgAdmin
- Deploy Rust App on VPS with GitHub Actions and Docker

Run the API on Your Machine
To run the feedback API project on your local machine and interact with the different endpoints, follow the steps outlined below:
- Download or clone the project from its GitHub repository at https://github.com/wpcodevo/rust-feedback-api and open the source code in your preferred code editor.
- Launch the Postgres and pgAdmin Docker containers by running the command
docker-compose up -d
. If Docker is not already installed on your machine, you can download and install it from their official website. - Apply the database migrations to the PostgreSQL database by running
sqlx migrate run
. If you don’t already have the SQLx-CLI installed on your computer, you can do so by running the commandcargo install sqlx-cli --no-default-features --features postgres
. - Once the database migrations have been completed successfully, run the command
cargo run
. This command will install the necessary packages and start the Axum development server.
Set Up the Rust API Project
Let’s begin by setting up the Rust API project. Open the integrated terminal in your code editor and run the command below. This will create a new binary application named rust-feedback-api
, containing all the necessary files to start building your Rust application:
Once the project has been generated, the next step is to install the necessary dependencies for building the API. In the terminal, run the following commands to add the required packages:
These commands will install essential libraries for handling requests, managing asynchronous tasks, serializing data, interacting with the database, and more.
Now, let’s get started by building a basic Axum HTTP server with a single health check route. Open the src/main.rs
file and add the following code:
src/main.rs
In the above code, we created an asynchronous function to contain the logic for the health checker route. Within the function, we defined a constant message and constructed a JSON response containing a success status and the message.
Next, we created the Axum server, registered the health checker route, and started the HTTP server on port 8000.
To test the health checker route, visit the URL http://localhost:8000/api/healthchecker
in your browser or API client.
Set Up a Database with Docker
Now that we have our basic HTTP server up and running, let’s proceed to set up a PostgreSQL database using Docker. In the root directory of your project, create a docker-compose.yml
file and add the following Docker Compose configurations:
docker-compose.yml
In the code above, we included an env_file
property to load the necessary environment variables for launching the Postgres and pgAdmin containers. To make these variables accessible to Docker Compose, create a .env
file in the root directory with the following secrets:
.env
With the environment variables in place, run the command docker-compose up -d
to start the Docker containers.
Connect the Rust App to the Running Database
That was quite a bit of setup boilerplate code! Now, let’s proceed to connect the Rust app to the running database server. Open your src/main.rs
file and replace its existing content with the code provided below:
src/main.rs
When you save the file, you should see a warning in your terminal indicating that the db
field is never read. This means we are on the right track.
Create and Push the Database Migrations
Now that our app can connect to the database, let’s proceed to the next step: setting up database migrations. This process will enable us to create the necessary table for storing feedback items.
We’ll utilize the SQLx CLI to manage the migrations and apply them to the database. If you haven’t installed the SQLx CLI yet, you can do so by running the following command:
With the SQLx CLI installed, execute the command below to generate reversible migration scripts. These scripts will be stored in a folder called migrations
within the root directory:
Navigate to the migrations
folder and open the file that includes ‘up‘ in its name. Inside this file, add the following SQL code to create a table in the database with columns representing the fields of a feedback item:
migrations/20240814125316_init.up.sql
Next, we need to define the SQL code that will reverse the changes made by the 'up' script. Open the file that includes the 'down' keyword in its name and insert the following code:
migrations/20240814125316_init.down.sql
Finally, run the command sqlx migrate run
to apply the migrations to the database. To verify that the migration was successful, open pgAdmin in your browser and use the credentials from the .env
file to connect to the Postgres server. Then, navigate to the tables section, where you should see the feedbacks
table.
Create the SQLX Database Model
Next, let's create the SQLx database model. This model needs to match the structure of the feedbacks
table we created earlier, as SQLx performs compile-time checks to ensure that the model's fields and types align with the corresponding database table.
If there are any mismatches, SQLx will raise errors. To set this up, create a model.rs
file within the src
directory and add the following code:
src/model.rs
Create the Data Schema
Now, let's define the structs that will handle the serialization and deserialization of data between HTTP requests, responses, and the database. These structs will serve as our data schemas. To create them, add a new file called schema.rs
inside the src
directory and include the following code:
src/schema.rs
Create the CRUD API Handlers
With our database model and data schemas in place, we can create the Axum route handlers responsible for processing HTTP requests. To get started, create a handler.rs
file and add the following imports:
src/handler.rs
Fetch All Records
Let's start with our first route handler, feedback_list_handler
. This handler will retrieve a paginated list of feedback items from the database and return them as a JSON response. In the src/handler.rs
file, add the following code:
src/handler.rs
Create a Record
Next, we'll implement the CREATE operation of our CRUD functionality. We'll name this handler create_feedback_handler
, and as the name suggests, it will be responsible for inserting new feedback items into the database. After successfully adding a new item, it will return the newly created feedback as a JSON response. Add the following code to the src/handler.rs
file:
src/handler.rs
Fetch a Record
Let's implement the second READ operation, which will return a single feedback item. We'll name this handler get_feedback_handler
, and its role will be to retrieve a specific feedback item from the database and return it as a JSON response. Add the following code to the src/handler.rs
file:
src/handler.rs
Edit a Record
Next, we'll implement the UPDATE operation in our CRUD functionality. We'll create a handler named edit_feedback_handler
, which will query the database, update the matching record, and return the updated record as a JSON response. Add the following code to the src/handler.rs
file:
src/handler.rs
Delete a Record
Finally, let's implement the DELETE operation, which is the last piece of our CRUD functionality. This handler will simply delete an item from the database and return no content upon successful completion. Add the following code to the src/handler.rs
file:
src/handler.rs
Complete API Handlers
Below is the complete code for the API handlers. You can copy and paste it into your src/handler.rs
file if you missed a particular step that is causing your code not to function as intended.
src/handler.rs
Create the API Routes
With the route handlers defined, let's set up the routes to invoke them. In the src
directory, create a route.rs
file and add the following code:
src/route.rs
Set Up CORS and Register the API Routes
To complete this tutorial, we need to register the routes on the server and configure CORS. Open the src/main.rs
file and replace its content with the code provided below:
src/main.rs
And we are done! We can now start making requests to the API. Ensure that the Postgres Docker container is still running, and then start the Axum development server with cargo run
if you haven’t done so already.
Let's test the CREATE CRUD functionality to ensure everything was implemented correctly. To access the Postman collection I used for testing the API endpoints, you can download the project from its GitHub repository and import the Feedback App.postman_collection.json
file into Postman.
Next, add the following JSON data to the request body of your API client, and then send a POST request to the http://localhost:8000/api/feedbacks/
URL.
You should receive a 201 response from the API, indicating that the new feedback item has been successfully added to the database. Additionally, you should see the added item in the JSON response. You can test the validation rules by omitting some fields from the JSON data or by using incorrect data types for the fields.
Conclusion
And that’s a wrap! In this comprehensive guide, you learned how to build a CRUD API in Rust using the Axum framework, SQLx, and PostgreSQL. I hope you found this article both helpful and enjoyable. If you have any questions or feedback, feel free to leave a comment below.