Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Easing into continuous deployment
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Chris Keathley
July 28, 2017
Programming
460
2
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Easing into continuous deployment
How we moved our team from static deployments into continuous deployment.
Chris Keathley
July 28, 2017
More Decks by Chris Keathley
See All by Chris Keathley
Solid code isn't flexible
keathley
5
1.1k
Building Adaptive Systems
keathley
44
3.1k
Contracts for building reliable systems
keathley
6
1.1k
Kafka, the hard parts
keathley
3
2k
Building Resilient Elixir Systems
keathley
7
2.5k
Consistent, Distributed Elixir
keathley
6
1.7k
Telling stories with data visualization
keathley
1
720
Leveling up your git skills
keathley
0
860
Generative Testing in Elixir
keathley
0
630
Other Decks in Programming
See All in Programming
【SRE NEXT 2026 Lunch Session】一人目専任SREの立ち上げを加速する ― AIと進めたオンボーディングで2分を0.04秒にした話
pkshadeck
PRO
0
2.3k
地域 SRE コミュニティ最前線 - ホンマでっかSRE勉強会
tk3fftk
0
220
Mujeres en SEO Summit 2026 - Greatest Disaster Hits en Web Performance
guaca
0
240
20260623_Loop Engineeringで自分の分身の問い合わせBotを作る
ryugen04
0
200
【やさしく解説 設計編 #0】DDDのコード、読めるのに分からない人へ
panda728
PRO
2
260
AI 輔助遺留系統現代化的經驗分享
jame2408
1
1.2k
AI駆動開発を妨げる技術的負債の解消アプローチ / ai-refactoring-approach
minodriven
17
8.9k
鹿野さんに聞く!『TypeScriptコードレシピ集』で磨く実践力
tonkotsuboy_com
4
1.1k
Claude Opus 4.6以後の受託開発エンジニアの変化(Claude Code開発ノウハウ大公開スペシャルbyクラスメソッド)
iidatakuma
1
590
「なぜそう決めたのか」を残し続ける仕組み ― Notion AI カスタムエージェント × Slack連携による設計判断の自動記録 - NIKKEI Tech Talk #47
niftycorp
PRO
0
260
1年で人数1.5倍、PR数5.5倍増。 品質とアウトカムはどうなったか、 何が効いたか
ike002jp
0
120
1B+ /day規模のログを管理する技術
broadleaf
0
130
Featured
See All Featured
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
2
320
A better future with KSS
kneath
240
18k
Accessibility Awareness
sabderemane
1
150
The Pragmatic Product Professional
lauravandoore
37
7.4k
RailsConf 2023
tenderlove
30
1.5k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
310
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
340
Thoughts on Productivity
jonyablonski
76
5.2k
Large-scale JavaScript Application Architecture
addyosmani
515
110k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
290
The Cost Of JavaScript in 2023
addyosmani
55
10k
The untapped power of vector embeddings
frankvandijk
2
1.8k
Transcript
Continuous Deployment Chris Keathley / @ChrisKeathley /
[email protected]
I work with a distributed team
I work with a distributed team
None
None
None
None
None
Warehouse
Warehouse API
Warehouse API Apps
The problem
Slow Iteration Cycle Deployment Deployment 2 weeks
Slow Iteration Cycle Deployment Deployment Deployment 2 weeks 2 weeks
Slow Iteration Cycle Deployment Deployment Deployment 3 weeks
Slow Iteration Cycle Deployment Deployment Deployment Hopefully someday
Large PRs
Unsure about state of the application
Unsure about state of the application
Unsure about state of the application
Unsure about state of the application
Unsure about state of the application
Rollbacks are a scam
None
None
Data Migration
Data Migration ?
Don’t do this
always Move forward
always Move forward
always Move forward
The goal should never be to roll back a deployment
The goal is to minimize the damage done by any
given deployment
There are bugs in your system
Solutions
We needed to deploy more often
So we did
Automated Deployment
What do you deploy?
Commit Sha
None
Jars
Artifacts
Git Tags
Containers
Your App
Your App Server
None
Master Branch How we merge our code PR
CI Github Registry Container Slack PR Notification
CI Kubernetes Deploy Auto-deploy Green builds of master
CI Kubernetes Deploy Auto-deploy Green builds of master Service A
Service B
CI Kubernetes Deploy Auto-deploy Green builds of master Service B
CI Kubernetes Deploy Auto-deploy Green builds of master Service B
Service A
CI Kubernetes Deploy Auto-deploy Green builds of master Service A
CI Kubernetes Deploy Auto-deploy Green builds of master Service A
Service B
Tests Metrics &
Integration Tests + Property Tests
Integration Tests TEst App DB Service
Modeling Users as FSMs logged_out logged_in login logout vote
Property Tests Add Todo Edit Todo Delete Todo
Property Tests Add Todo Edit Todo Delete Todo
Property Tests Add Todo Edit Todo Delete Todo
Property Tests Add Todo Edit Todo Delete Todo
Generate Commands
Generated Commands [{:add_todo, “Test Todo”, 1}, {:edit_todo, "Edited", 2}, {:delete_todo,
"", 1}, {:add_todo, “New Todo", 3}, {:delete_todo, "", 2} {:edit_todo, “Edited Todo”, 2}]
Generate Commands
Generate Commands
Generate Commands
Generate Commands
Generate Commands
Generated Commands [{:add_todo, “Test Todo”, 1}, {:edit_todo, "Edited", 2}, {:delete_todo,
"", 1}, {:add_todo, “New Todo", 3}, {:delete_todo, "", 2} {:edit_todo, “Edited Todo”, 2}]
Generated Commands [{:add_todo, “Test Todo”, 1}, {:delete_todo, "", 2}] [{:add_todo,
“Test Todo”, 1}, {:edit_todo, "Edited", 2}, {:delete_todo, "", 1}, {:add_todo, “New Todo", 3}, {:delete_todo, "", 2} {:edit_todo, “Edited Todo”, 2}]
Prometheus Service A Grafana Service B Service C
Prometheus Service A Grafana Service B Service C Slack
# Alert for any instance that have a 95th percentile
> 200ms. ALERT APIHighRequestLatency IF api_http_request_latencies_second{quantile="0.95"} > 0.2 FOR 5m ANNOTATIONS { summary = "High request latency on {{ $labels.instance }}", description = "{{ $labels.instance }} has a median request latency above 1s (current value: {{ $value }}s)", }
Track “Business” Metrics
None
Feature releases and flags
None
Features aren’t all or nothing
Features != Deployments
Deployment
Deployment Features
Deployment Features
User
User staff?(user) == true
User staff?(user) == false
User staff?(user) == false
defmodule MyApp.FeatureFlags do alias MyApp.User def foo_enabled?(%User{staff: is_staff}), do: is_staff
def foo_enabled?(_), do: false def bar_enabled?(%User{staff: is_staff}), do: is_staff def bar_enabled?(_), do: false end
Browser Feature Service
Feature Service Feature Service Feature Service
Feature Service Feature Service Feature Service
Feature Service Feature Service Feature Service
You have updates ready! Reset
None
With larger Traffic numbers you could use percentages
Alchemy
“Transmute lead code into gold in production”
Prior Art: https://github.com/github/scientist
Users_Controller DB User.all
DB User.all UserService.all
User.all UserService.all ==
def index(conn) do users = old_query() render(conn, "index.json", users: users)
end
def index(conn) do users = experiment("users-query") |> control(&old_query/0) |> candidate(&new_query/0)
|> run render(conn, "index.json", users: users) end
def index(conn) do users = experiment("users-query") |> control(&old_query/0) |> candidate(&new_query/0)
|> candidate(&fancy_query/0) |> run render(conn, "index.json", users: users) end
1) Shuffles test order 2) Runs Each test in parallel
3) exports the data Alchemy
DB User.all UserService.all Control Candidate Control UserController
None
1) Do the results match? 2) How long does each
test take to return? Measure
No more cutovers
DB User.all UserService.all
DB User.all UserService.all User service
Migrations
http://blog.datomic.com/2017/01/the-ten-rules-of-schema-growth.html
DB Schema App Application Coupling
Your application knows about your schema
Lets remove a column
Lets remove a column 1) all application code needs to
stop using that column
Lets remove a column 1) all application code needs to
stop using that column 2) Update all ETL processes
Lets remove a column 1) all application code needs to
stop using that column 2) Update all ETL processes 3) Update Reporting
Lets remove a column 1) all application code needs to
stop using that column 2) Update all ETL processes 3) Update Reporting 4) Remove the column
Lets remove a column 1) all application code needs to
stop using that column 2) Update all ETL processes 3) Update Reporting 4) Remove the column Split all of these up
Lets Add a column
Lets Add a column 1) Add the column
Lets Add a column 1) Add the column 2) Eventually
start using it
Prefer Additive Migrations
CI Kubernetes Deploy Auto-deploy Green builds of master
CI Kubernetes Deploy Auto-deploy Green builds of master Migration
CI Kubernetes Deploy Auto-deploy Green builds of master Migration DB
Chat-Ops
None
Chat is…
Chat is… Centralized
Chat is… Centralized Transparent
Chat is… Centralized Transparent Open
Try to do operational tasks in chat
None
defmodule Hedwig.Responders.Ping do use Hedwig.Responder @usage """ hedwig: ping -
Responds with 'pong' """ respond ~r/ping$/i, msg do reply msg, "pong" end end
None
Generate grafana graphs
None
Deploy
None
Team Building
Conclusion
These are tools at our disposal
Deploy more often, safely
Thanks Chris Keathley / @ChrisKeathley /
[email protected]