How to Manage Connection Strings in AWS Elastic Beanstalk Multi-Environment Ecosystem

How to Manage Connection Strings in AWS Elastic Beanstalk Multi-Environment Ecosystem

When you have to move your app through multiple environments, connections to databases can be a serious pain.

The Context (and the pain)

I was building an app in ASP[.]NET Core 3.1 with a MySQL database and deployed on AWS with Elastic Beanstalk. In my local environment, I make use of the appsettings.json file to set up a connection string for my database.

"ConnectionStrings": {
    "ConnectionString": "server=my-database-endpoint;database=MyDevDb;user=admindb;password=mysecretpassword"
  }

The app has been deployed in a "dev" (stands for "development") environment. Everything was working properly. But as the project was moving on, came the moment to deploy on a pre-production environment, for the client to test things alongside the process. Also, thinking about the production environment became a reality. So, from one environment, I then needed to manage three. The infrastructure on AWS looks like below. This is simplistic, as I've chosen to omit certain services. Security groups, for instance, are not represented here.

infrastructure.png

Here is the beginning of the complications. I have one codebase but three environments to deploy on. Each is connected to its own MySQL RDS database. At each deployment, I need to carefully change the connection string in appsettings.json in order to point to the right database. When using one appsettings.json file per environment (appsettings.{environment}.json), I need to change the ASPNETCORE_ENVIRONMENT variable in my project properties. Want to learn more about environments in ASP[.]NET Core? Here's the official documentation from Microsoft.

It became really painful to make all these changes again and again at each deployment. Also, when I forget, an app in one environment will try to connect to another environment database and it can be dramatic. Deployments became too risky, stressfull, and error-prone. It was urgent to find a solution.

The solution

There are several ways to make deployment easier in this context. In my case, I wanted to keep my codebase unchanged, and to make it database-agnostic. The easiest solution I've found is to let the Elastic Beanstalk environment manage its own connection string.

Elastic Beanstalk environment properties

Elastic Beanstalk allows to set up variables called environment properties, which are platform-specific, just as connection strings. We can then define our connection string as an environment property and get access to it programmatically. According to the environment, we are now sure to construct the right connection object and to connect to the right database. Yay!

To set up an environment property, let's connect to the AWS account. Next, choose the Elastic Beanstalk service, select your environment and go to Configuration -> Software and click the Edit button on the right. Here we have an "Environment properties" panel. let's create one as shown below :

env_property_creation.png

As we can see, I've created an environment property named "CONNECTION_STRING" with a value set to my connection string. You can find the AWS documentation about environment properties here.

Now I can get this value in my ASP[.]Net Core project, in the startup.cs file :

var connectionBuilder = new MySqlConnectionStringBuilder(
                Environment.GetEnvironmentVariable("CONNECTION_STRING"));          
 services.AddDbContext<MyDbContext>(options =>
                    options.UseMySql(connectionBuilder.ConnectionString));

When the app is deployed on its environment, the Environment.GetEnvironmentVariable method will retrieve the string value stored in the environment property named "CONNECTION_STRING". Then the app can make a proper connection to the appropriate database. I repeated the process for all three environments and I don't need to update my code anymore. Every deployment is now smooth and each environment is managing the appropriate connection string for the right database. Problem solved! ;-) The infrastructure now looks like below :

infrastructure.png

And you, how do you manage your database connections through your environments? Do not hesitate to share it in the comments :-)

Did you find this article valuable?

Support Daniel Lawson by becoming a sponsor. Any amount is appreciated!