
{"id":7813,"date":"2020-11-30T16:51:21","date_gmt":"2020-11-30T16:51:21","guid":{"rendered":"https:\/\/rax-stg-wp-aws.com\/blogs\/multi-tenant-data-and-application-management-through-a-devops-pipeline\/"},"modified":"2026-11-03T19:29:04","modified_gmt":"2026-11-03T19:29:04","slug":"multi-tenant-data-and-application-management-through-a-devops-pipeline","status":"publish","type":"blogs","link":"https:\/\/www.rackspace.com\/en-gb\/blogs\/multi-tenant-data-and-application-management-through-a-devops-pipeline\/","title":{"rendered":"Multi-tenant data and application management through a DevOps pipeline"},"content":{"rendered":"<p><strong><em>Originally posted in January 2020 at the Onica blog <a href=\"https:\/\/onica.com\/blog\/\">here<\/a>.<\/em><\/strong><\/p>\n<p>As the world of DevOps has grown, the ability to pipeline a web deployment or use infrastructure as code to&nbsp;recreate the same stack over and over has become a standard practice.<\/p>\n<p><strong>Promote your data through various environments<\/strong><\/p>\n<p>Through the many patterns that power this type of pipeline deployment, one of&nbsp;the most common traits is that the database and its data remain in place, with each tier having&nbsp;a similar configuration to be sure the deployment and pipelines work as intended.&nbsp;<\/p>\n<p>What if you need to promote your data through the environments and be as flexible and deployable as any&nbsp;other artifact? That was the story behind our design and implementation&#8211;;to pipeline and deploy a multi-tenant&nbsp;application for one customer.&nbsp;<\/p>\n<p>Let\u2019s take a look at the steps we took to plan and implement this solution and how we dealt with the complexities of designing the common web stack for multi-tenancy, configuration, and being able to change out the database flexibly with every deployment.<\/p>\n<p><strong>Planning<\/strong><br \/>\nThe components of the stack were a PHP application server, fronted by an Nginx\u00ae host and&nbsp;backed by a MySQL\u00ae&nbsp;database. We had to make several key decisions regarding the framework for building&nbsp;the rest of the project to make sure it would be flexible, scalable, and reliable.<\/p>\n<p><strong>Namespace<\/strong><\/p>\n<p>With multiple customers, and multiple environments for each customer and possibly multiple tenants for&nbsp;a single customer, we needed a larger naming strategy. Affecting everything from AWS\u00ae&nbsp;CloudFormation\u00ae;,&nbsp;configuration, AWS Identity and Access Management (IAM) &nbsp;policies, AWS Systems Manager (SSM) Parameter Store&nbsp;access, and cost controls, we decided on the following namespace: `<em><strong>&lt;ShortCustomerName&gt;-&lt;ProjectNum&gt;-Environment&gt;`<\/strong><\/em><\/p>\n<p>A customer gets a shortened name. Each project for that customer gets a unique global&nbsp;project number, such as <strong>xy-0146<\/strong>, that is used as a component of each stack with an <strong>Amazon S3<\/strong>&nbsp;prefix,&nbsp;such as the&nbsp;<strong>AWS SSM path<\/strong>. For example:<\/p>\n<p>\n<strong>xy-0146-dev<\/strong><br \/>\n<strong>xy-0146-qa<\/strong><br \/>\n<strong>xy-0146-prod<\/strong><\/p>\n<p>In addition to a customer namespace, we use a common namespace for shared infrastructure&nbsp;such as the <strong>VPC<\/strong>, or non-production and production Amazon ECS clusters.<\/p>\n<p><strong>Compute<\/strong><\/p>\n<p>For each stack, the data source and application build might change, making the ability to deploy quickly&nbsp;and roll back critical, and the number of customers and environments made density and sprawl a&nbsp;&nbsp;concern as well.<\/p>\n<p>Containers were a natural fit, providing density and flexibility. By using Amazon ECS, the pipeline could&nbsp;create immutable container images and task definitions for each build and each managed database.<\/p>\n<p><strong>Database<\/strong><\/p>\n<p>For maximum flexibility in creating and destroying databases and managing the lifecycle and&nbsp;promotion of the data through snapshots, we used Amazon Relational Database Service (RDS). With this tool,&nbsp;you can do all the work against a database in development and snapshot it. The snapshot is then the source&nbsp;of truth for each higher-tier deployment.<\/p>\n<p><strong>Timestamp<\/strong><\/p>\n<p>Finally, to integrate the data lifecycle with the deployment cycle, we use a timestamp&nbsp;to version the database at any given time and to be part of the naming component. You can make the Amazon RDS databases with AWS CloudFormation within the customer namespace, but name them with the timestamp of&nbsp;the initial snapshot, allowing multiple side-by-side launches within a given environment at the time of deployment.<\/p>\n<p>The most important part is tracking which database is active and what databases exist as part of the&nbsp;deployment to ensure no databases are made and orphaned. To do this, use the active timestamp with&nbsp;an AWS SSM parameter store, and with other relevant database connection secrets that the pipeline&nbsp;pulls to determine the correct database to connect to and how to connect.<\/p>\n<p><strong>Operations<\/strong><br \/>\nNow, let&#8217;s look at our operations.<\/p>\n<p><strong>Infrastructure<\/strong><\/p>\n<p>By combining these components, AWS CloudFormation deployed the common underlying infrastructure,&nbsp;and then the customer and project-specific deployments on top of that. For the necessary flexibility,&nbsp;we used Stacker, a Python module for programmatically creating AWS CloudFormation.<\/p>\n<p>The rolling nature of Amazon ECS and immutable task definitions and containers means that, despite&nbsp;the change in data sources behind the deployment, we could deploy the Amazon ECS services as long as we made the database. This created an interesting challenge as both databases must be running&nbsp;until the new container versions stabilize. Normally, you could use the outputs of the singular DB stack&nbsp;to get running information for it. However, because we needed two, the timestamp became a critical part of&nbsp;the stack names, and we tracked it in the Parameter Store as the source of truth.<\/p>\n<p><strong>Pipeline<\/strong><\/p>\n<p>We divided the stacks logically to keep the database separate, to allow the deployment and flow as needed,&nbsp;with two parallel databases running during the deployment. The following rough steps describe the process,&nbsp;and the diagram depicts the logical flow of the artifacts as we deploy the new task definitions and databases:<\/p>\n<ol>\n<li><strong>Database snapshot<\/strong>&nbsp;holds the latest development database.<\/li>\n<li><strong>The parameter stores<\/strong> stacks current active database stack information for later.<\/li>\n<li><strong>The parameter store<\/strong>&nbsp;creates a *DB stack* from the snapshot with a timestamp of the snapshot and activates it.&nbsp;<\/li>\n<li>The&nbsp;<strong>Parameter store<\/strong> obtains the latest build and configuration and creates an Amazon ECS service for the active DB name.<\/li>\n<li><strong>The deployment pipeline<\/strong>&nbsp;waits for the Amazon ECS service to stabilize with the new task definition.<\/li>\n<li>The p<strong>arameter store<\/strong> deletes the original timestamped database.<\/li>\n<\/ol>\n<p>In the case of a failure, this means the existing Amazon ECS service continues to run even if&nbsp;<br \/>\nthe new DB and new task versions fail to stabilize. Thus, we get a clean rollback and uninterrupted access.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/26508-body-Picture1_29.png\" alt=\"devops pic 1\" \/><\/p>\n<p><strong>Conclusion&nbsp;<\/strong><\/p>\n<p>A lot of considerations went into the creation of a pipeline that would support a multi-tenant application&nbsp;and a specific use case for the database\u2019s lifecycle. Many of the practices we put into use are just as&nbsp;valuable to add to any architecture. Strong namespacing on stacks, tags, and instances can add clarity&nbsp;and flexibility to deployments and a clear way to separate configuration data. Database stacks based&nbsp;on Amazon RDS and snapshots allow a data flow you can use for anything from standing up duplicate&nbsp;data environments dynamically or immutable deployments of data across environments.<\/p>\n<p>Interested in learning what your business can gain by leveraging DevOps? Check out <a href=\"https:\/\/onica.com\/services\/managed-cloud-operations\/\">Rackspace Onica\u2019s Managed Cloud Operations service<\/a>. If you\u2019re&nbsp;ready to get started, <a href=\"https:\/\/onica.com\/contact\">get in touch with our team today<\/a>&nbsp;to learn how Onica, a Rackspace Technology company, can help you leverage DevOps to accelerate innovation&nbsp;and lead the market.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Multi-tenant data and application management through a DevOps pipeline<\/p>\n","protected":false},"author":2,"featured_media":7815,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","format":"standard","meta":{"content-type":"","nid":"26508","content_type":"blog","created_by":"10130","authored_on":"2024-01-14T16:51:21+00:00","field_article_industries":"","tag_category":"Technical","field_blog_author_text":"by Rackspace Technical Staff","seo_description":"Configure per-site Web Application Firewall (WAF) policy with IP address restriction rules. Control inbound access based on IP.\r\n","field_featured_image":"","insights_image":"\/wp-content\/uploads\/2026\/blog_technical_images\/26508-insights_image-devops-technical-blog-1-insights.jpg","field_partners":"","rxt_platforms":"Applications, Amazon Web Services (AWS), Bare Metal Private Cloud, AWS Data","product":"","publisheddate":"2020-11-30T16:51:21","rxt_solutions":"Cloud Adoption & Migration, Cloud Management & Operations, Cloud Optimization","opengraph_tag":"","x_tag":"","teaser_flag":"Technical Blog","seo_titile":"Data and application management DevOps pipeline | Rackspace","field_topics":"","field_slug":"multi-tenant-data-and-application-management-through-a-devops-pipeline","footnotes":""},"categories":[178],"tags":[204],"class_list":["post-7813","blogs","type-blogs","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-technical"],"_links":{"self":[{"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/blogs\/7813","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/blogs"}],"about":[{"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/types\/blogs"}],"author":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/comments?post=7813"}],"version-history":[{"count":3,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/blogs\/7813\/revisions"}],"predecessor-version":[{"id":9689,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/blogs\/7813\/revisions\/9689"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/media\/7815"}],"wp:attachment":[{"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/media?parent=7813"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/categories?post=7813"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/tags?post=7813"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}