Software Environment Architecture
Why do companies need different environments?
Your company may have development, test, quality assurance, and production environments or maybe they call them something for example different pre-production and production.
The need for having different environments is for isolation of changes, testing, as well as debugging and troubleshooting issues.
Logical Environments
I define a logical environment as a place where software could be deployed to fulfil a specific purpose. For example Development, Testing, Quality Assurance or Serving actual users (Production).
Below is a template of logical environments and their purposes.
Physical Environments
A physical environment is the actual deployment of running infrastructure and applications.
Ideally, your physical environments line up perfectly with your logical environments. In reality different projects, vendors, departments and epochs have cobbled together different IT systems which different purposes, budgets and naming conventions.
You should at least make an effort to try and classify what the purpose of each environment is, even if it is not fully complaint.
Physical Environment Matrix
Describes the tenancies / instances / subscriptions and how they map to the defined purposes of your logical environments
Application Matrix
Describes the unique naming conventions of software across your logical environments
Version Matrix
Audits the version of software across your logical environments
Patterns / Common issues
Single Physical Environment Multiple Logical Environments
Rather than set up proliferate lots of full stack environments test1, test2, test3, point logical environments to other ones and introduce bugs (no-no), or spend your entire life maintaining mocks a much simpler solution is to follow an approach which is similar to how multi-tenancy works.
You have 1 deployed artifact in one logical environment e.g test but allow the consumer to send something e.g (a header or a characteristic of their user jwt token) which can route in real-time the processing of something to a different physical instance (that is in the same overall logical environment). e.g a request from test1 may be processed by test2.
This pattern is useful in the case where something is a cross cutting concern e.g authorization and where data does not need have integrity / be consistent across domain boundaries.
Feature Toggles
Removes the need for many environments, but temporarily increases code current state complexity.
Anti Patterns / Common issues
I hear these quite a bit. Here are common rebuttals to symptoms that are actually reflecting underlying root problems.
We need more environments
No you don’t. You need to replace your long running integrations / feature branches with continuous deployment, trunk based development and high quality environments that replicate production. You also need to reduce the difference between production and non production environments in both version and infrastructure
We need the full stack environments in all environments
No you don’t. You need to confirm what each environments purpose. You should have at least one environment that is full stack. Can you identify what would have been caught with a full stack environment that could not have been caught earlier in the SDLC through another quality strategy.
We need to mock everything
No…. you don’t. Your test approach probably very ineffective and this is most likely a symptom of a high coupled and brittle architecture.
We should mock everything
No… you shouldn’t, mocking everything provides a false sense of security. Complexity is emergent and interesting failures come from interactions between components. https://www.goodreads.com/book/show/10258783-drift-into-failure
It’s okay if we point one environment to another environment
No… its not. Your going to introduce corrupt data and create false negatives. Instead use mocks.
We need a special environment for testing performance (or some other cross cutting concern)
This confuses environment definition with environment purpose. Define what each environment is used for.
I can’t test my infrastructure as code / devops changes until I check my code in
Operations folk sometimes see operations work as outside the SDLC. E.g a build server is in the development environment (its not…. its a production tool). All changes whether they be spinning up an environment or changing the scripts which spin up the environment should be able to be tested in advance. In this case spin up a separate ‘Dev’ environment in a different tenancy to test changes in advance before merging them in.
The data is stale
Refresh your data from production regularly. If the data is sensitive then generate it or scrub it of anything sensitive before restoring to previous application.
Shared Development Databases
https://www.troyhunt.com/unnecessary-evil-of-shared-development/
Patterns
Consolidation Pattern
Save money by consolidating infrastructure to a single App Service / Container / Server in a Dev or Test environment.
Side environments
An environment which is effectively a production environment but is used to serve other environments. E.g a Tenancy that orchestrates backups, stores sensitive security logs that cannot be deleted by admins etc.