Backend overview
Welcome to the backend section of the Quinck Dev Wiki! ⚡️ This section is dedicated to all things backend. Here you will find tips, tools, best practices and patterns for backend development.
API design
The API design is a crucial part of the backend development process. It’s the interface that the frontend and other services will use to interact with the backend. A well-designed API can make the difference between a smooth and a painful development process.
The most used standard for API design is the REST (Representational State Transfer) architecture. Read more about REST here.
Fundamental principles of API design:
- Consistency: The API should be consistent in its design and naming conventions.
- Predictability: The API should be predictable and easy to understand.
- Flexibility: The API should be flexible and easy to extend.
We exclusively use the OpenAPI standard for API design. OpenAPI is a standard for defining RESTful APIs, and it’s widely used in the industry.
The workflow for backend development is always the following:
Define OpenAPI specification ➡️ Generate/Define models in code based on OpenAPI schemas ➡️ Implement the API ➡️ Deploy ➡️ Repeat
Guidelines
Rest APIs are about resources defined by paths and verbs.
-
Use paths to define on what resource to inreact
- Each path in REST is a resource and must be named accordingly
- Use noun instead of verbs or actions
- The paths should only indicate the resource
- Use single words as much as possible for each path part
- Do not write:
/organizations/:id/organizationMembers - Instead write:
/organizations/:id/members
- Do not write:
- Avoid long names
- Avoid over structured paths
- Avoid repetitions
- do not define different paths for different interaction modes
- instead define one path and apply different verbs
-
Use verbs to define how to interact with a resource
- Common verbs:
POSTto create,GETto retrieve,PATCHto update,PUTto replace,DELETEto remove/delete - i.e.
- Having defined the resource path
/petsthe interaction could be defined withPOSTto create a new petGETto retrieve/search the pets
- Having defined the resource path
/pets/:id(referring to a pet with id:id) the interaction could be defined withGETto retrieve the petPUTto replace the pet informationPATCHto partially update the pet informationDELETEto delete the pet
- Having defined the resource path
- Common verbs:
Schemas
-
Never define inline schemas but instead define named schemas in components
-
do not
paths:/users:get:summary: Get UsersoperationId: getUsersresponses:"200":description: Successful response with userscontent:application/json:schema:type: arrayitems:type: objectproperties:firstName:type: stringexample: "Mario"lastName:type: stringexample: "Rossi"email:type: stringexample: "example@example.com" -
instead do
paths:/users:get:summary: Get UsersoperationId: getUsersresponses:"200":description: Successful response with userscontent:application/json:schema:type: arrayitems:$ref: "#/components/schemas/User"components:schemas:User:type: objectproperties:firstName:type: stringexample: "Mario"lastName:type: stringexample: "Rossi"email:type: stringexample: "example@example.com"
-
-
Inline schemas are only allowed in case of paramaters used once
paths: /users: get: summary: Get Users operationId: getUsers parameters: - in: query name: firstName schema: type: string required: false responses: "200": description: Successful response with users content: application/json: schema: type: array items: $ref: "#/components/schemas/User"components: schemas: User: type: object properties: firstName: type: string example: "Mario" lastName: type: string example: "Rossi" email: type: string example: "example@example.com"Database design
The database design is another crucial part of the backend development process. It’s the storage that the backend will use to store and retrieve data. A well-designed database can help development process, performance and scalability.
There are two main types of databases: SQL and NoSQL. Read more about the differences here.
SQL vs NoSQL
We mostly use the following databases:
- PostgreSQL (SQL)
- MongoDB (NoSQL)
When to use SQL:
- When you need to store structured data
- When you need to perform complex queries or aggregations
- Performance is a serious concern
When to use NoSQL:
- When you need to store unstructured data (like JSON)
- You can’t predict the structure of the data
Languages and frameworks
Unlike the frontend, the backend has a wide variety of languages and frameworks to choose from. This is because the code runs on the server, and the server can be any machine or environment.
The following are our languages of choice:
- TypeScript: used for general purpose API development
- Go: used for high-performance and concurrent services or APIs
- Rust: special cases where performance and security is a serious concern
We developed our internal templates and framework for the three languages, to make the development process faster and more consistent.