RFC: Multitenancy

Published on: 10 Dec 2015 by: Michael Noonan

Update: Multi-tenant deployments will be shipping as part of Octopus Deploy 3.4 and Beta 2 has been released! See the 3.4 Beta 2 blog post for the latest information.

Update: We have revisited this RFC based on some compelling customer feedback! Read the updated RFC proposing Tenant as a first-class concept...

Octopus Deploy is designed to deploy software releases, and promote them through a series of environments with repeatable results. Octopus models this typical scenario nicely, but it doesn't scale well for multi-tenant applications. Let's consider the example discussed in our guidance for multi-tenant deployments using Octopus Deploy...

NameBadge make HR software for large corporate customers. They provide the software as a SaaS offering to their customers, and host the web site and associated services for them. Due to how the application is architected, for each customer, they deploy a different SQL database, a copy of an ASP.NET website, and a copy of a Windows Service.

The key issue in this scenario is that the same components need to be deployed multiple times, one for each end-customer, which makes it different from the scenarios Octopus is typically designed to handle.

To manage this kind of situation today we make three recommendations:

Sadly both environment-per-tenant and project-per-tenant scale poorly in Octopus and that is the problem we would like to solve, starting with this RFC!

We will primarily concentrate on environment-per-tenant in this RFC since it is by far the most popular method used today


This is a big RFC, but it's also a big set of features! We encourage you to take the time to understand what we're proposing, how it will affect your situation, and help us steer!

Multi-tenancy is painful

After helping many of our customers deal with multi-tenant deployments in Octopus we've seen the following themes:

Did we miss something significant? Leave a comment!

Managing lots of environments

The Octopus deployment engine and API can handle thousands of environments. The main complaint from our customers is the user experience for managing more than just a handful of environments is poor.

  • The Environments page itself doesn't scale well. Slow load times, no filtering/search, lots of vertical scrolling, and there can be a lot of repeated information when many tenants are hosted on shared infrastructure.
  • The Dashboard and Project Overview pages do not scale well. Slow load times, no filtering/search, there is no way to aggregate state, they overflow horizontally and horizontal scrolling is hard.
  • Every time you add a new environment you need to update lots of disconnected resources:
    • Lifecycle phases that should include the new environment
    • Deployment targets/machines that host the software for the new environment
    • Accounts that enable deployment to the new environment
    • Steps that should be scoped to the new environment
    • Variables that should be scoped to the new environment

Adding a new tenant

Based on our recommendation for environment-per-tenant you would need to:

  • Create new environment for the tenant called Production-CustomerA
    • Add the Production-CustomerA environment to all required lifecycle(s)
    • Add the Production-CustomerA environment to all required account(s)
    • Add the Production-CustomerA environment to all required deployment target(s)
  • Create a new library variable set called Production-CustomerA to contain the variables specific to the new tenant
    • You need to know the full set of variables that are required for the new tenant
    • Manually enter each variable name and value being careful not to make a mistake!
    • Individually scope all of these variables to the Production-CustomerA environment
  • For each required project:
    • Add the Production-CustomerA variable set to all required Project(s)
    • Optionally scope deployment step(s) to the Production-CustomerA environment
    • Deploy the latest release to the Production-CustomerA environment
  • Profit!

If the end-customer requires a staging environment for testing and approving releases to their production environment, you'd have to repeat all of that for Staging-CustomerA.

Many of our customers automate the process for creating new tenants via the Octopus API, but that doesn't relieve the pain involved in the ongoing management of tenants over time.

No single place to manage a customer

When you are managing a customer with one or more environments you often need to jump around the Octopus user interface with little or no help navigating between pieces of information related to the same customer. Using a naming convention for environments, variable sets, accounts and dedicated machines is a really good idea, but it only gets you so far.

Library variable sets are global

Consider the case where certain important customers should only be managed by a select few people. This can be achieved by setting permissions to the environments and ensuring each variable in the library variable set are scoped properly to the environment. However the library variable set itself is not connected to an environment - it is considered a global resource.

What we propose to do about multi-tenancy in Octopus Deploy

We are proposing to introduce a series of new features across the breadth of Octopus Deploy. We believe these features will benefit the vast majority of our customers in addition to those managing multi-tenant deployments.

Have something to say? Leave a comment!

Managing environments as groups using tags

One of most common problems we've discussed so far is dealing with lots of environments, especially that you cannot aggregate environments on the dashboards, and you cannot deal with environments as groups. We propose introducing tags to enable these types of scenarios.

Firstly you would determine which tags you want to make available by creating tag sets in the Library, with the valid list of tags for each tag set. Which tag sets and tags you create is completely up to your discretion. In this example we have created several tag sets each representing different attributes we want to leverage throughout Octopus Deploy.

Library - Tag Sets

Note these tags mean very little at the moment - read on to see how each of these different attributes can be leveraged to enable some compelling scenarios.

Octopus Deploy could now make these tag sets available when configuring your environments, and you could configure which actual tags you want applied to each environment. Take a look below and you'll notice the tag sets have been ordered to match the order from the Library. In this example we have tagged the Production-Tenant-Mobil environment as belonging to the Production phase, hosted in the Shared 2 hosting group, with the selected modules, and as a VIP customer.

Environment Settings - Tags

If you have lots of environments it would be a lot easier if you could manage which tags are applied to environments in bulk. This would enable you to add a new tag set, and very quickly tag all of your environments.

Environments - Bulk Tag Edit

Improved environments page

Once you have configured some tag sets and tagged some environments Octopus could aggregate the environments page by tag sets. You could drill directly in to one of the tags and be presented with the matching environments.

Environments - Rollup

Improved dashboards

After configuring your tags and environments you could configure the dashboards to group by one of the tags. Octopus could aggregate the most important information about the group including the number of environments, overall status of the group with indicators that draw your attention if necessary, the range of releases that have been deployed to the contained environments, and the progress of rolling out the latest release to the contained environments.

In this example we are grouping environments by the phase tag.

Dashboard - By Phase

Some people might be more interested in customer type or another aggregation.

Dashboard - By Customer Type

Similarly the project overview could be grouped by tag showing the release history as it does today.

Project Overview - By Phase

Project Overview - By Customer Type

Clicking on one of the groups could drill in to that group and show more details about the environments in the group. In this example we have clicked on the 3.2.6-3.2.7 to see details of that group. Notice we can now arrange the environments vertically (no more horizontal scrolling) and potentially filter environments by name or another tag. We can also show the release history for each environment, and the Deploy button so you can upgrade all of the production tenants from the same screen.

Project Overview - Details - Phase - Production

Referencing environments by tag

When you want to refer to an environment in Octopus Deploy today you need to reference it explicitly, by the environment name. After you have created some tag sets you could start referencing environments by tag. Consider this example of configuring a deployment target as a shared host for multiple environments before tag sets.

Deployment Targets - By Name

With tags you could simplify this deployment target, configuring it once, and allowing Octopus to dynamically resolve which environments apply at runtime.

Deployment Targets - By Tag

While referencing environments by tag will be more convenient in many ways, it could become more confusing depending on the complexity of each situation. To help tame the additional complexity we could provide a design view, similar to what we've done for designing the version rules for Channels.

Select Environments - Designer

Managing lifecycles, deployment targets and accounts

Provided you can reference environments by tag, managing environments in lifecycles, deployment targets and accounts could become more concise and powerful. For example, whenever you add a new environment Octopus could automatically include the environment in the correct deployment targets, lifecycle phases, and accounts according to its tag(s). We just saw an example of a deployment target. In this example we have defined a simple lifecycle where the environments in each phase are driven by the Phase: * tags.

Lifecycle - By Tag

In this example all environments tagged with Phase: Production would be authorized to use the Synergy Production Subscription account.

Accounts - By Tag

Scoping variables and steps

Scoping variable values would be more convenient if you could scope based on tags. In this example the variable value would be used when we deploy to any of the production tenants defined by the Phase: Production tag.

Scoping Variables - By Tag

Similarly scoping deployment steps could become much simpler. In this example we have customized our deployment process based on several different tags. Firstly we will deploy the Exploration module to tenants tagged with Module: Exploration. We will also notify the priority support team when a VIP customer, tagged with Customer type: VIP, has been upgraded. We will also send a tailored email notification to our production tenants, tagged with Phase: Production, once their deployment has been completed successfully.

Scoping Steps - By Tag

Managing tenant-specific variables

The next piece of the puzzle is managing variables specific to each tenant. To deal with this we are planning to let you add variables directly to an environment, but before we get on to that, how do you know which variables need to be added to these environments? Imagine if projects could define the variables required for each different environment, and then each environment could prompt you for the variables it requires. We are proposing to introduce the concept of variable templates.

Variable templates

Variable templates could allow a project to define which variables are required for a successful deployment. We think variable templates will be more manageable as composite parts, just like project variables and library variable sets are today. Each project could define the set of variables that change between environments, optionally including common variable templates from the library. In this example the project has defined two specific variable templates and included two variable set templates from the library.

Project - Variable Set Template

Each of these variable templates could be defined in a similar fashion to how parameters are defined for a step template, where you can provide the variable name, a label, help text, a default value and an input control type, such as single-line/multi-line text box, sensitive/password box, check box, or drop down.

Environment variable sets

Many customers doing multi-tenant deployments with Octopus today will create a library variable set for each tenant. We propose to make variables available as part of the environment settings. This way you could specify all of the environment-specific variables as part of the environment itself, and Octopus would automatically and implicitly scope these variables to that environment. When you deploy a release to a particular environment Octopus will automatically merge the variable set from that environment.

Projects are already mapped to environments by way of lifecycles, so it would be natural to assume that an environment will use variable templates from any projects it is linked to via lifecycle.

Mapping Projects to Environments

In this example the Synergy project will be deployed to this environment, and based on the variable templates defined in Synergy, we require:

  • CustomerName and TenantAlias from the Standard tenant details library variable set template
  • StorageAccountUri from the Common storage account library variable set template
  • SynergyDatabase and SynergyApiKey from the Synergy project
  • MojoDatabase from the Mojo project

Environment Settings - Variables

In this case we haven't defined a value for the MojoDatabase variable and are being prompted to set that value.

Variable inspector

Today, variables in Octopus Deploy generally come from projects, library variable sets, or step templates. Adding environments as a source for variables will simplify some aspects of managing variables, but diagnosing problems with variables could become more difficult. We are proposing to add a variable inspector that will make it easier to get an overview of all of the variables in a project, their source, and if there are any problems.

Variable Inspector

It's not just about multi-tenancy

Managing large-scale multi-tenant deployments in Octopus Deploy is clearly painful today. We believe the features proposed in this RFC will benefit the vast majority of our customers. Consider these scenarios:

  • Other use-cases similar to multi-tenancy:
    • Managing multi-region deployments in the public cloud where you deploy to several geographic regions but consider them all as Production.
    • Teams with multiple test engineers where each person has their own test environment.
    • Dynamically commissioning/decommissioning feature branch environments for testing new features in isolation before going through the normal Dev/Test/Production lifecycle.
  • Starting a new project, you configure the Dev and Test environments. Weeks later you want to add Staging and Production environments, but have forgotten which new variables need to be added for these new environments.
  • Simply managing lots of environments and variables for a variety of reasons.
  • Wanting to keep your environment-specific variables directly on the environment for reasons of cohesion/authority/security.
  • Wanting to add some more structure to your project variables.

Wrapping up

With these features in place we hope the pain involved with managing large-scale multi-tenant deployments will be eased significantly. Consider what would be involved in creating a new tenant:

  • Create new environment for the tenant called Production-CustomerA
    • Add tags as appropriate
    • Enter the prompted variables
  • Deploy the latest release(s) to the Production-CustomerA environment
  • Profit!

Leave a comment

What do you think? This is your chance to speak up and help us build the right features for your environment.