Everything these days is a blah-blah-as-a-service, and your development lifecycle should be no different. When you provide a well working and documented services that your team can use to provision resources and introduce change in a controlled way; you will enable your teams to innovate and focus on building value for your customers. How do you do that? Let’s examine how to make this self-service thing something that doesn’t need to ‘be built’ but simply happens automatically. Your teams’ cultural norms will demand it.

Break Down the Barrier

One of the biggest cultural challenges that affect your teams’ ability to innovate are the barriers between your teams. If you find yourself in the following situations then you need a self-service mentality on your team:

  • Waiting — You are waiting on another teammate to provision an environment for you.
  • Hesitation — Your team is afraid to break something while innovating.
  • Compliance  — Your compliance requirements are complicated and often overlooked.
  • Accuracy — Your team is provisioning environments with defects.

Let’s look at three common challenges and objections to getting your team self-sufficient: managing costs, scope, and dependencies.

Controlling Costs

A major inhibitor of getting your team deploying environments on-demand is controlling the costs. There’s a whole book that could be written about building a culture around cost control. It’s probably something that comes naturally to your management team and your solutions architects — but probably nobody else. Self-service environments can quickly produce revenue by increasing productivity and allowing for rapid innovation, however, it can also become expensive equally as quickly.

You want self-service environments to be as close to production as possible. That includes using the same deployment scripts for your self-service as you do in production. You control the costs by changing the cost factors:

  • Instance Size & Instance Count — Launch small, cost-effective instances. You can keep autoscaling policies in place, but keep your desired and max counts low to control costs.
  • Mock Services — Do you need to deploy live services for every environment? If not, launch mock services where possible.

More often than not, environments become abandoned and forgotten. It happens; people go on vacation, get sick or simply forget to tear down their old environments when they’re finished. Consider working into your environment an automated teardown. As an example, each self-service environment could be configured to self-destruct after a day or a week. It sounds more difficult than it actually is, checks out a tool like Cloud Custodian to automate your cost control. You’ll get some pushback here, especially at first because your team may fear losing their work. This is the time to reinforce that if it’s not committed to your shared code repository, then it doesn’t exist.


Every engineer, regardless of discipline, has made something too generic. As software developers we want our features to be as dynamic and useful as possible and many times this mindset is to our detriment — even with automation and infrastructure-as-code.

The purpose of self-service is to allow as many teammates as possible the ability to launch an environment of their own. You want them to be self-sufficient. It’s very easy to build in too many options (and optional options) that confuse your users and do the opposite. If your new team member is pinging you in slack asking which of the 37 checkboxes they need to launch their environment, then your self-service pipeline isn’t useful.


A self-service environment should be a one-button deployment. This is difficult to get right, but generally, you want to follow these guidelines:

  • Feature Rich Defaults — Make your default options the most feature rich. Deploy the whole stack. Make users choose things they don’t want. Odds are they have no idea and need everything anyways.
  • Obvious Options — The parameters should be things they actually know. Don’t bother with putting in HTTP endpoints, license codes or passwords. Don’t make them have to look it up.
  • Design for Failure — Failure is something that will happen — plan accordingly. Write in useful error handling and error messages and anticipate configuration issues. Much like writing tests when users encounter bugs, when someone encounters an issue you didn’t account for, immediately implement a case for that in the pipeline.

Designing for failure is something we’ve covered in the past, it’s relevant in many facets of software development. Pipelines, self-service, and infrastructure-as-code are no exceptions — engineers are users too.


It’s easy for the cultural aspect of self-service to get lost in all the technical challenges, but it’s all part of the bigger picture.  As your team works through these challenges with an automation-first mentality and with self-service in mind, things will come together more quickly. New members will join your team and begin working right-away, your colleagues will be performing UAT and Sprint Demos without requiring your help and your cloud engineers can focus on helping your team deploy more frequently.

Continue reading our blog series on DevOps Culture with posts like DevOps Culture: An Automation-First Mentality and The DevOps Culture: Empowering Your Team.

Stelligent Amazon Pollycast
Voiced by Amazon Polly