Alireza Tanoomandian
2024-06-03Those who work around building or maintaining software(s) might face a situation, problem, or requirement in our working environment or daily life that raises an idea of software that can make it robust, fixed, or fill a gap and make the process more pleasant. Or you might be at the beginning of starting a SaaS company startup with an inspiring idea! By the way, you're about to create software. But wait! What is SaaS?
Here are some definitions:
Software as a Service (SaaS) is a cloud-based software model that delivers applications to end-users through an internet browser. Source: AWS
Software-as-a-service, or SaaS for short, is a cloud-based method of providing software to users. SaaS users subscribe to an application rather than purchasing it once and installing it. Users can log into and use a SaaS application from any compatible device over the Internet. Source: CloudFlare
Software as a service (SaaS) allows users to connect to and use cloud-based apps over the Internet. Common examples are email, calendaring, and office tools (such as Microsoft Office 365). Source: Microsoft Azure
As you can see in common, software served through the cloud to the user without installation on the user's computer is called SaaS, and the user still needs a tool, like a web browser or a mobile app to reach it at the cost of subscription, freemium, or free. Sound familiar!
source: cloudflare
But why should we design our software in this way?
Every model, at its core, has pros and cons. It is related to the business and users to decide but from the users' point of view, the pros of SaaS often stand on top against the cons. Here are some:
As you can see, developing standard software as a service or other related types is challenging; we should think about scalability, security, code shipment, testing, etc. Due to its complexity, there are common practices that should be applied to the software. These practices are also known as the Twelve Factors app or 15 Factors app, which has much in common but three more! We explore the precisely as follows:
One codebase tracked in revision control, many deploys
A codebase is any single repo or setup repos that share a root commit and its various versions are controlled by the version control system, such as Git or Subversion. For an application always present a single codebase, a one-to-one correlation!
The codebase is the same across all deploys, but its version might vary in each deployment. For example, deployed commits might vary between the staging, UAT, or production.
Explicitly declare and isolate dependencies
Nowadays, most applications use a package manager for their dependencies. This factor said that the application should not rely on system-wide installed packages and all dependencies should be declared explicitly and precisely. Furthermore, it has to use a dependency isolation tool during execution to ensure that system-installed packages do not leak into the application.
For example, your application shouldn't rely on external packages like curl
in the running environment or vice versa. If the application requires to shell out to system tool, that should be vendored (e.g. add binary executable of the package to project) into the app.
One benefit of explicit dependency declaration is that it simplifies setup for developers new to the app. They can easily onboard to the project and quickly set up their development environment.
Store config in the environment
An app's config is everything likely to vary between deploys on different environments. This includes:
Config
and Code
should be separated, because Config
might vary between deployments but the Code
doesn't. Plus, sharing the code is more secure as no credentials will be exposed.
There is an approach for managing the configuration that saves config to files like config/database.yml
and makes them unchecked in version control systems to not commit the in repo. It's a far better way to keep them in code but still, there is a chance that the file was checked and mistakenly committed to the repo!
Another approach, and also recommended, is to store configuration in environment variables that are easy to change between deployments, but also have cons that the configuration might accidentally left behind in code! It is also a language and OS-agnostic standard. they also can group for different environments by their name.
Treat backing services as attached resources
A backing service is any service the app consumes over the network as part of its normal operation. Examples include datastores (such as MySQL or CouchDB), messaging/queueing systems (such as RabbitMQ or Beanstalkd), SMTP services for outbound email (such as Postfix), and caching systems (such as Memcached).
This factor mentions that there should be no difference between the local and third-party services. From the app view, both are attached resources that are accessed via URL or other locator/credentials stored in the configuration without any code change.
source: 12 factors app
Each backing service should be attachable to the application. So in case of any problem, such as a hardware issue, can replace them.
Strictly separate build and run stages
Generally, a code base is transformed into the deployment stage through 3 steps:
Although technology stacks can increase or decrease these stages, the main processes are as explained. The twelve-factor app uses strict separation between the build, release, and run stages. For example, it is impossible to make changes to the code at runtime, since there is no way to propagate those changes back to the build stage.
Every release should always have a unique release ID, either time-related like 2024-03-14T10:15:45
or incremental like v19
, to identify which version is running. Any change must create a new release.
This is the first part of the post. In the next post we are going to explore the rest of remained factors, so keep going!
Hope you enjoyed it!
Alireza Tanoomandian
2024-06-03