Currently we run one instance of each "machine". Every instance has a "maximum" number of users and visitors it can serve, before the average CPU usage gets bigger than the baseline. When we get more users than one instance can support, their experience will suffer, by longer load times or increased latencies.
Before we get into increasing computational power, we have to move the databases to a separate instance. The SQL server database on the Windows machine is struggling with the amount of memory and by having the databases inside of the instances, they're not stateless.
This database instance can be a self-managed EC2 instance or a managed RDS instance. The latter is preferred obviously. However, SQL server RDS instances are pricey, so we also want to migrate the application database to MySQL. With that we can move both databases (application and WordPress) to the MySQL RDS instance.
This RDS instance will be placed in a private subnet, preventing external entrance. The databases can only be accessed through the applications, not directly. The
sg-rds-mysql security group will only allow the IP-addresses of our servers.
One way of dealing with the increased processing needs is to change the instance type to a bigger more powerful one. But we probably don't need that much CPU power all the time. We don't want to have a big, expensive server idling at night.
This is were the elasticity of the cloud is super-awesome. By creating an auto scaling group, AWS will create additional identical (hence the stateless requirement) instances when needed (scale out) and terminates them when they are unnecessary (scale in). A load balancer will divide the traffic (users) between these instances.
Another advantage of this latest setup is you can have instances created in multiple availability zones. If one zone goes down, the scaling group will launch replacement instances in the other zones.
Everything after that is "far" in the future. So I didn't bother sketching it. However, the database availability can be improved by having a Multi-AZ (availibility zone) setup. In that case a second instance, in a different AZ, will be standby and ready when a failure of the first occurs.
You can also add a read-replica in another AZ. This will offload reading from the master instance, increasing overall performance.
Preferably though, I would want to use Aurora by that stage. The Aurora engine has even better duplication.
We need to refactor our monolith first.