Pragmatic decisions for deploying a serverless RESTful API on AWS
In « Pragmatic decisions for your RESTful API », I described a set of standards and best practices that, in my opinion, you should implement if you are building a RESTful API. In this new series of posts, I will describe how to deploy a RESTful API in the serverless world on Amazon Web Services, using code written in Typescript. I will use, as a base, the famous petstore API provided as an example of an OpenAPI specification. Let’s start with the overall repository structure.
Overall GIT Repository structure
When most people create an application, they usually think they need the following : a backend and a frontend. The way it usually goes afterwards is that a myapplication-backend repository is created, and a myapplication-frontend repository is created and development can start after establishing a list of routes that will be needed for the API being created. However, when deploying a serverless RESTful API on AWS, this is only the tip of the iceberg.
Your backend and frontend are obviously important, but if you want to do things properly, you will also need :
- a proper API specification, which will allow you to generate a clean API documentation
- an infrastructure to support this API : API gateway, Lambdas, Cognito for the authentication, one or multiple databases etc. Note that ideally, this infrastructure should be coded using tools such as Terraform, instead of created manually through the AWS console
- one or multiple client libraries: ideally, you are creating an API to allow other people to use it. The easier you make it for other people to use it, the more popular your API can become, so publishing one or more client libraries, eventually in multiple langages, can be a good idea
- tests : unit and functional tests can be included in the code of your frontend and backend, but ideally, you will also have a set of E2E tests which could be separated from the code of your backend
Single vs multi repository
You could split all of these components in multiple repositories, which means you would end up with a list of the following repositories, for the petstore example :
- petstore-backend
- petstore-frontend
- petstore-infra
- petstore-spec
- petstore-tests
If you are a small team, you will probably have a single person work on multiple parts of the application. For example, if you want to add a field to the API somewhere, you will need to update the spec, the model in the backend, and maybe display the new field in the frontend. Therefore, it will be much easier and much more convenient to work on a single repository, separating the different components using directories. This will also allow you to have a much cleaner commit history, a single commit corresponding to the addition of a specific feature in the specification, backend and frontend altogether.
That’s why, unless you really have specific teams of developers dedicated to each component I mentioned above, I really advise you to go for a single repository, named petstore, with the following directories :
-- backend
-- frontend
-- infra
-- spec
-- tests
Possible variants for tests and infra
If you have already built serverless projects, you are already probably guessing the structure that will be used for the backend : a mono-repository with a suite of packages, each package corresponding to a specific part of the application. For the petstore example we will have something like :
backend
-- common: Common files: models, helpers etc...
-- packages
---- pets
------ package.json
Here, you could argue that the infrastructure as code needed for pets could be included as sub-directories in the backend, using the following structure :
backend
-- common: Common files: models, helpers etc...
---- infra : Common infrastructure for all packages, API gateway, Cognito user pool etc.
-- packages
---- pets
------ infra : Infrastructure needed for the pets component only
Whether you choose the former or the latter is entirely up to you. If the same team of developers is responsible for the application backend and the infrastructure, it might be better to go for the latter. However, if a different team is in charge of the infrastructure and the backend, you might be better off with a single infra directory at the root of the repository.
You could argue the same thing for tests, saying they could be included in multiple directories in the backend and frontend. Let’s split the various tests you should have in your application to make it rock solid :
- unit tests : these tests can indeed be included directly in the frontend and backend, with a specific extension. For example, if you have a Pet.ts file for your pet model, you should also have a Pet.spec.ts or Pet.test.ts for the unit tests of the Pet model.
- functional tests : functional tests can also be included directly with specific extensions, directly in the backend and frontend of your application
- end to end tests : that’s where things get a bit trickier. You will be testing an API, so your E2E tests should be a set of HTTP requests that will be sent to your API to verify it works as expected. You can use Postman or Insomnia to do these tests. These E2E tests will definitely need their own directory. You could include them in the backend, in a backend/tests directory, however I don’t advise you to do this : since these tests will mostly be configuration files for Postman or Insomnia, they are not really part of the backend, which is why I really advise you to put them in a tests directory at the root of the repository.
A single repository to rule them all
Unless you are a very large team, I really advise you to go for a single repository, with the following directory structure :
-- backend
-- frontend
-- infra
-- spec
-- tests
with the possibility to include the infrastructure as a code in your backend and frontend directories.
If you would like to see how you can build your API specification using OpenAPI (basically the content of the spec directory), you can refer to this article.
To learn about how you build the code of the other directories, stay tuned, more articles will follow.