AWS Startups Blog

Five Tips to Get Started with Continuous Delivery

Guest post by Florian Motlik, CTO of Codeship


For all startups, moving fast, iterating quickly, and building on top of feedback from early users and customers are keys to growing into a successful company. Adrian Cockcroft, AWS Community Hero and one of the people behind Netflix’s success with its AWS cloud infrastructure, has stressed that “speed wins the marketplace.” There is constant pressure from many different sides on startups and their products to change and improve.

Pressures startups are under to change and improve.

Pressures startups are under to change and improve.

Continuous integration and delivery are two best practices to help keep up with constant change and achieve this speed boost.

What is Continuous Integration and Delivery?

Continuous integration is the process of running your whole test suite any time you commit code to your repository. This makes sure your application works as expected and changes do not introduce unexpected behavior.

Continuous delivery means ensuring your code is always deployable or even gets released into your staging and production infrastructure any time you make a change to your main codebase. This includes running your tests, which makes continuous integration a part of continuous delivery. This helps get new features and improvements out to your customers quickly and get feedback early.

Having a great software development and delivery process can have enormous impact on a startup, as explained in our e-book on workflow best practices.

With that in mind I want to introduce you to five tips Codeship and our customers have used successfully for a long time to help move fast and build great products.

1. Testing Is to Make Users Happy, Not Validate Software

In my opinion, one of the core misconceptions people have about testing is that testing is about validating a piece of software works. In actuality, testing is there to ensure you make your users happy.

When building a product your customers want two things from you:

  1. Constant innovation to support new needs. They want to trust us to build something that they’ll need in a year or two as well.
  2. Not breaking old things.

Proper testing ensures you can keep building your application without constantly hurting your users. It also gives you the freedom to experiment since you know you’re not hurting your users when you pass all your tests. It gives you the speed and security needed to iterate quickly.

It’s vitally important to trust your test suite and deploy immediately if the results green. You need to feel completely secure once everything passed, so you can deploy anything, anytime. That gut feeling that tells you everything will be OK even though you’re pushing on Friday night before going out with friends. This leads to much faster experimentation and go-to-market with new features.

Your early users are what drives your product development and growth. Make sure you don’t push them away by constantly breaking your application.

2. Let Your Repository Drive Your Infrastructure

In their day-to-day work, developers shouldn’t have to care about the larger production infrastructure. They should focus on code and which code is in which branch. When code is merged between branches, it should get deployed automatically.

For example, merging code from a feature branch into a staging or production branch shows the intent to get this deployed into the respective part of the infrastructure. Developers can stay focused on the code and move on to the next task immediately without having to think a second about how to get this out into production.

In our experience, the repository is a great way to trigger this workflow as we’re using it constantly and there is no ambiguity. There is only one last commit at any point. This way developers can focus on their code and the repository, a place they spend all of their time anyway.

3. Build an Immutable Infrastructure

Infrastructure that runs for a long time is hard to replicate, and can lead to potential issues like bugs that only come up after weeks of use. Sometimes it even gets changed in a way that isn’t recorded anywhere. All of these are major issues that take away precious time from your developers who should be focusing on product development.

In comparison, an immutable infrastructure comprises immutable components that are replaced for every deployment, rather than being updated in-place. Those components are started from a common artifact that is built once per deployment and can be tested and validated. The artifact can even be redeployed if you want to roll back from a future version in case something bad happens. The common artifact can be built through automation, but doesn’t have to be.

Immutable Servers are like Legos: rebuild and replace instead of repairing them.

Immutable Servers are like Legos: rebuild and replace instead of repairing them.

Immutability is independent of any tool or workflow for building the artifacts. Its best use case is in a cloud or virtualized environment. While it’s possible in nonvirtualized environments, the benefit doesn’t outweigh the effort.

Building an immutable infrastructure forces your team to fully automate the setup and deployment of any component as they have to be replaced constantly. When one server breaks for any reason, you can replace it immediately, just like a Lego brick.

By replacing any server that is not behaving as expected, you can implement autohealing of your infrastructure easily, as replacing pieces is a constant action anyway.

Docker and containers in general help a lot with getting this set up, but noncontainer tools like Packer for building AMIs can also help, and we’ve worked with them for a long time. AWS CloudFormation together with userdata and cloud-init configuration is another tool that can help you building and configuring your systems through code stored in your codebase.

4. Measure and Log Everything

After fully automating the deployment of each part, you need to make sure you have proper logging and metrics in place to understand how your infrastructure is behaving at any point.

This data is the lifeblood of your operations and stability. At any point you need to be able to see the status of your system and add additional metrics. You need to have alarms in place in case something goes wrong and everyone on your team needs to be able to easily access all that data without having to jump through hoops. It’s not enough to just collect that data. If it’s not easily accessible to everyone you might as well not collect it at all.

There are many services out there to collect your logs and metrics. AWS CloudWatch supports metrics as well as logging.

Use AWS CloudWatch to get insight into your infrastructure.

Use AWS CloudWatch to get insight into your infrastructure.

AWS Elastic Beanstalk supports log shipping to Amazon S3. There’s also Papertrail and Librato Metrics (which we use) and many others. Most importantly, pick one provider and start collecting your metrics and logs.

Once you have that infrastructure in place make sure that every change in your codebase has proper logging and metrics embedded with it. Operationalizing your code is key to getting the necessary insight, and you should check every code change for it during code review.

5. Turn off Access to Your Machines

Being able to access your production infrastructure anytime sets a very bad incentive for your team. You won’t start collecting your metrics and logs in a central location early on. You will also build an infrastructure designed for debugging in production.

To set the incentives right for your team, one of the best actions you can take is simply turning off direct access to your production infrastructure. Or at least make sure somebody has to jump through hoops to do it. This would even let you remove SSH private keys from the AWS servers completely so access is fully closed down.

This forces everyone to make sure any data necessary to debug a problem is properly stored in the central metric system. Having direct access to your infrastructure is a shortcut that is very destructive and carries large security risks. Taking away the access limits potential security issues.

Conclusion

Transitioning to continuous delivery and a great software development process is an important task for any software startup as it will speed up your development while making sure you’re not breaking your product for your customers. Being able to iterate constantly and get feedback from your customers without breaking your application will help you win your market.

Make sure you invest enough time and staff in getting this started early so you can reap the benefits throughout the lifetime of your company.