SlideShare a Scribd company logo
1 of 73
Download to read offline
A Scalable Rails app
  Deployed in 60
      seconds




                       1
Ben Scheirman



• Director of Development at ChaiONE
• Microsoft MVP, ASP Insider
• Certified ScrumMaster
• Former .NET Ninja, now Rails/iPhone
  aficionado
                                        2
Ben Scheirman




• ...not affiliated with Heroku

                                   3
So you have a fantastic app?




                               4
5
6
7
7
7
7
7
7
8
8
9
10
11
x 1,000?
           11
12
x 10,000?
            12
writes


reads




         13
writes


reads




         x 1,000,000?
                        13
14
On-Demand
        15
# Users by time of day
400



300



200



100



 0
 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM



                                           16
# Users by time of day
400



300



200



100



 0
 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM



                                           16
# Users by time of day
400



300



200



100



 0
 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM

        Only need massive scale from 9am - 9pm

                                                 16
Expected Users For PR Campaign
900



675



450



225



  0
  Mar 1 Mar 15 Apr 1 Apr 15 May 1 May 15 Jun 1 Jun 2



                                                       17
Expected Users For PR Campaign
900



675



450



225



  0
  Mar 1 Mar 15 Apr 1 Apr 15 May 1 May 15 Jun 1 Jun 2



                                                       17
SCALE




        18
19
Awesome Shredder Art by Dan Barret

                                20
gem install heroku
             Awesome Shredder Art by Dan Barret

                                             20
• Platform as a service for Rack-based apps
• Scale easily
• Great workflow
• Free to start / Friendly Pricing
• Complete command-line API
                                              21
Deploy a rails app in 5 steps


             git init
             git add .
             git commit -m “My First Commit”
             heroku create
             git push heroku master
Creating morning-summer-18..... done
Created http://morning-summer-18.heroku.com/ | git@heroku.com:morning-summer-18.git




                                                                                      22
Deploy a rails app in 5 steps


             git init
             git add .
             git commit -m “My First Commit”
             heroku create
             git push heroku master
Creating morning-summer-18..... done
Created http://morning-summer-18.heroku.com/ | git@heroku.com:morning-summer-18.git




                                        LET THAT SOAK IN...

                                                                                      22
Using git for deployment is f***ing
              GENIUS




                                      23
Technology




             • Amazon Web Services
             • Caching w/ Varnish
             • Debian Linux
             • Erlang Routing Mesh
             • Nginx
             • PostgreSQL
                                     24
25
How Heroku Scales




                    26
How Heroku Scales
  or WTF is a Dyno?




                      26
How Heroku Scales
  or WTF is a Dyno?




                      26
How Heroku Scales
  or WTF is a Dyno?




                      26
How Heroku Scales




                    27
How Heroku Scales




                    27
How Heroku Scales




                    27
When to add dynos




• Increasing response times
• “Backlog Too Deep” Error
                                           28
Always Measure




• New Relic RPM
• Apache Bench



                                   29
Heroku Tips



         • Multiple Heroku apps for Test, Staging,
              Production
         • Learn the awesome-ness of Taps
         • Heroku logs
         • Heroku Console
         • Useful addons: New Relic, Exceptional
                                                     30
Backups




          31
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        32
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        33
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        34
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        35
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        36
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        37
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        38
Coping with the Free Single Bundle
  task :backup do
    bundle_name = "my-backup"
    heroku_app = ENV['app']

      def wait_for_response_text(text)
        heroku_app = ENV['app'] #lame, I know
        begin
          puts "."
          bundles = `heroku bundles --app #{heroku_app}`
        end while bundles.match(text).nil?
      end

      #check for existing bundle
      bundles = `heroku bundles --app #{heroku_app}`
      unless bundles.match /has no bundles/
          `heroku bundles:destroy #{bundle_name} --app #{heroku_app}`
          wait_for_response_text 'has no bundles'
      end

      puts "Capture bundle #{bundle_name}..."
      `heroku bundles:capture #{bundle_name} --app #{heroku_app}`
      wait_for_response_text "complete"

      puts "Downloading bundle..."
      `heroku bundles:download #{bundle_name} --app #{heroku_app}`
      timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp
      new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz"
      mkdir "backups" unless File.exists? "backups"

      `mv #{heroku_app}.tar.gz #{new_path}`
      puts "Bundle saved to #{new_path}" end
end
                                                                        39
One-button Deployments
task :deploy do

  heroku_app = ENV['app']

  heroku_config = Hash.new
  Rake::Task["heroku:backup"].invoke

  puts "Turning maintenance on..."
  puts "** " + `heroku maintenance:on --app #{heroku_app}`
  sleep 15 #maintenance mode causes your slug to be recompiled

  puts "Pushing changes to heroku..."
  puts "** " + `git push #{git_remotes[heroku_app]} master`

  puts "Migrating heroku databases..."
  puts "** " + `heroku rake db:migrate --app #{heroku_app}`

  puts "Setting up config variables..."
  heroku_config.each_pair do |k, v|
    puts "** " + `heroku config:add #{k.to_s.upcase}=#{v}`
  end

  puts "Turning maintenance mode off"
  puts "** " + `heroku maintenance:off --app #{heroku_app}`

  puts "DEPLOYMENT DONE!"
end


                                                                 40
Delayed Jobs




               41
Delayed Jobs


def send_bulk_emails

      BulkEmailSender.send_a_ton
      flash[:notice] => "Ok we sent them"

end




                                                           41
Delayed Jobs


def send_bulk_emails

      BulkEmailSender.send_a_ton
      flash[:notice] => "Ok we sent them"

end




                          def send_bulk_emails

                                BulkEmailSender.send_later(:send_a_ton)
                                flash[:notice] => "Ok we sent them"

                          end


                                                                      41
Delayed Jobs




               42
Delayed Jobs


> gem install delayed_job
> rails g delayed_job
> rake db:migrate




                                           42
Delayed Jobs


> gem install delayed_job
> rails g delayed_job
> rake db:migrate




                        > heroku workers 1
                           simple-snow-68 now running 1 worker
                        > heroku workers +1
                           simple-snow-68 now running 2 workers



                                                                  42
Delayed Jobs




               43
Delayed Jobs



$0.05 per hour / worker
(even when it's not processing Jobs)




                                                      43
Delayed Jobs



$0.05 per hour / worker
(even when it's not processing Jobs)




                     http://github.com/pedro/delayed_job/commit/
                     09d7657e1fc7d25072e6c5e73ede20d6e1185eac

                     http://bit.ly/9Qokff



                                                                   43
Delayed Jobs
Pedro's Fork / auto-scale branch




                               44
Delayed Jobs
             Pedro's Fork / auto-scale branch



//lib/delayed/job.rb
def after_create
  Manager.scale_up if self.class.auto_scale &&
    Manager.qty == 0
end

//lib/delayed/worker.rb
Manager.scale_down if count.zero? &&
  Job.auto_scale &&
  Job.count == 0




                                                 44
• Read-only file system
 • some gems don’t work
 • File uploads?
 • Temp Directory
• SSL, memcached, Full-text-search expensive
• Bound-by Amazon’s SLA
                                               45
contact = {

! :blog => http://flux88.com,
!
! :twitter => @subdigital,
!
! :email => ben@scheirman.com

}

                                46
47

More Related Content

What's hot

Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014biicode
 
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopPuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopWalter Heck
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnAppWalter Heck
 
PuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetPuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetWalter Heck
 
DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)Soshi Nemoto
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)Soshi Nemoto
 
Puppet and Apache CloudStack
Puppet and Apache CloudStackPuppet and Apache CloudStack
Puppet and Apache CloudStackPuppet
 
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....Alessandro Cinelli (cirpo)
 
Development with Ansible & VMs
Development with Ansible & VMsDevelopment with Ansible & VMs
Development with Ansible & VMsJeff Schenck
 
From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012Carlos Sanchez
 
Augeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet treeAugeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet treeJulien Pivotto
 
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Carlos Sanchez
 
Getting Started With CFEngine - Updated Version
Getting Started With CFEngine - Updated VersionGetting Started With CFEngine - Updated Version
Getting Started With CFEngine - Updated VersionCFEngine
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersMarcin Chwedziak
 
Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Carlos Sanchez
 
From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011Carlos Sanchez
 
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...Puppet
 
Create Development and Production Environments with Vagrant
Create Development and Production Environments with VagrantCreate Development and Production Environments with Vagrant
Create Development and Production Environments with VagrantBrian Hogan
 
Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Michele Orselli
 
Instruction: dev environment
Instruction: dev environmentInstruction: dev environment
Instruction: dev environmentSoshi Nemoto
 

What's hot (20)

Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014Dependencies Managers in C/C++. Using stdcpp 2014
Dependencies Managers in C/C++. Using stdcpp 2014
 
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & HadoopPuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
PuppetCamp SEA 1 - Using Vagrant, Puppet, Testing & Hadoop
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
 
PuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of PuppetPuppetCamp SEA 1 - Use of Puppet
PuppetCamp SEA 1 - Use of Puppet
 
DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)
 
DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)DevOps(4) : Ansible(2) - (MOSG)
DevOps(4) : Ansible(2) - (MOSG)
 
Puppet and Apache CloudStack
Puppet and Apache CloudStackPuppet and Apache CloudStack
Puppet and Apache CloudStack
 
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
BDD - Buzzword Driven Development - Build the next cool app for fun and for.....
 
Development with Ansible & VMs
Development with Ansible & VMsDevelopment with Ansible & VMs
Development with Ansible & VMs
 
From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012From Dev to DevOps - FOSDEM 2012
From Dev to DevOps - FOSDEM 2012
 
Augeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet treeAugeas, swiss knife resources for your puppet tree
Augeas, swiss knife resources for your puppet tree
 
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
Continuous Delivery with Maven, Puppet and Tomcat - ApacheCon NA 2013
 
Getting Started With CFEngine - Updated Version
Getting Started With CFEngine - Updated VersionGetting Started With CFEngine - Updated Version
Getting Started With CFEngine - Updated Version
 
Effective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 DevelopersEffective Doctrine2: Performance Tips for Symfony2 Developers
Effective Doctrine2: Performance Tips for Symfony2 Developers
 
Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012Puppet for Java developers - JavaZone NO 2012
Puppet for Java developers - JavaZone NO 2012
 
From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011From Dev to DevOps - Apache Barcamp Spain 2011
From Dev to DevOps - Apache Barcamp Spain 2011
 
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
Building and Testing from Scratch a Puppet Environment with Docker - PuppetCo...
 
Create Development and Production Environments with Vagrant
Create Development and Production Environments with VagrantCreate Development and Production Environments with Vagrant
Create Development and Production Environments with Vagrant
 
Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)Vagrant for real (codemotion rome 2016)
Vagrant for real (codemotion rome 2016)
 
Instruction: dev environment
Instruction: dev environmentInstruction: dev environment
Instruction: dev environment
 

Viewers also liked

Path: Why you need another social media app
Path: Why you need another social media appPath: Why you need another social media app
Path: Why you need another social media appPeriscope
 
Salesforce.com Partner Meetup - New York -10/18/12
Salesforce.com Partner Meetup - New York -10/18/12 Salesforce.com Partner Meetup - New York -10/18/12
Salesforce.com Partner Meetup - New York -10/18/12 Salesforce Partners
 
Dyno cycling behavior of Heroku
Dyno cycling behavior of HerokuDyno cycling behavior of Heroku
Dyno cycling behavior of HerokuShunji Konishi
 
herokuでfacebookアプリを作ったお話
herokuでfacebookアプリを作ったお話herokuでfacebookアプリを作ったお話
herokuでfacebookアプリを作ったお話Naoto Koshikawa
 
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's BusinessCodeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's BusinessHeroku
 
Social Design :: Social Network Design
Social Design :: Social Network DesignSocial Design :: Social Network Design
Social Design :: Social Network DesignJaume Teixi
 
Developing a Real Time Ad-Server on Heroku
Developing a Real Time Ad-Server on HerokuDeveloping a Real Time Ad-Server on Heroku
Developing a Real Time Ad-Server on HerokuSalesforce Developers
 
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different Heroku
 
Getting Started with Heroku
Getting Started with HerokuGetting Started with Heroku
Getting Started with HerokuLaunchAny
 

Viewers also liked (11)

Path: Why you need another social media app
Path: Why you need another social media appPath: Why you need another social media app
Path: Why you need another social media app
 
Salesforce.com Partner Meetup - New York -10/18/12
Salesforce.com Partner Meetup - New York -10/18/12 Salesforce.com Partner Meetup - New York -10/18/12
Salesforce.com Partner Meetup - New York -10/18/12
 
Dyno cycling behavior of Heroku
Dyno cycling behavior of HerokuDyno cycling behavior of Heroku
Dyno cycling behavior of Heroku
 
herokuでfacebookアプリを作ったお話
herokuでfacebookアプリを作ったお話herokuでfacebookアプリを作ったお話
herokuでfacebookアプリを作ったお話
 
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's BusinessCodeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
Codeacademy's Linda Liukas at Heroku's Waza 2013: Code is Everyone's Business
 
Social Design :: Social Network Design
Social Design :: Social Network DesignSocial Design :: Social Network Design
Social Design :: Social Network Design
 
Developing a Real Time Ad-Server on Heroku
Developing a Real Time Ad-Server on HerokuDeveloping a Real Time Ad-Server on Heroku
Developing a Real Time Ad-Server on Heroku
 
Continuous Deploy
Continuous DeployContinuous Deploy
Continuous Deploy
 
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
Mattt Thompson at Heroku's Waza 2013: Mobile is not Different
 
Getting Started with Heroku
Getting Started with HerokuGetting Started with Heroku
Getting Started with Heroku
 
ταξίδι στη γλώσσα
ταξίδι στη γλώσσαταξίδι στη γλώσσα
ταξίδι στη γλώσσα
 

Similar to A Scalable Rails App Deployed in 60 Seconds

LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경Mintak Son
 
Virtual Environment and Web development using Django
Virtual Environment and Web development using DjangoVirtual Environment and Web development using Django
Virtual Environment and Web development using DjangoSunil kumar Mohanty
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf Conference
 
OpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudOpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudIsaac Christoffersen
 
2015 DockerCon Using Docker in production at bity.com
2015 DockerCon Using Docker in production at bity.com2015 DockerCon Using Docker in production at bity.com
2015 DockerCon Using Docker in production at bity.comMathieu Buffenoir
 
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...POSSCON
 
DockerCon EU 2015: Trading Bitcoin with Docker
DockerCon EU 2015: Trading Bitcoin with DockerDockerCon EU 2015: Trading Bitcoin with Docker
DockerCon EU 2015: Trading Bitcoin with DockerDocker, Inc.
 
Symfony Deployments on Heroku
Symfony Deployments on HerokuSymfony Deployments on Heroku
Symfony Deployments on HerokuStefan Adolf
 
Hosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceHosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceQuinlan Jung
 
How I hack on puppet modules
How I hack on puppet modulesHow I hack on puppet modules
How I hack on puppet modulesKris Buytaert
 
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...Docker, Inc.
 
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...Christy Norman
 
Dockercon EU 2014
Dockercon EU 2014Dockercon EU 2014
Dockercon EU 2014Rafe Colton
 
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...Docker, Inc.
 
From Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOSFrom Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOSSusan Potter
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Clinton Dreisbach
 
Create ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageCreate ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageAndrii Lundiak
 
Using Prometheus to monitor your build pipelines
Using Prometheus to monitor your build pipelinesUsing Prometheus to monitor your build pipelines
Using Prometheus to monitor your build pipelinesLander Van den Bulcke
 

Similar to A Scalable Rails App Deployed in 60 Seconds (20)

LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
LetSwift 2017 - 토스 iOS 앱의 개발/배포 환경
 
Virtual Environment and Web development using Django
Virtual Environment and Web development using DjangoVirtual Environment and Web development using Django
Virtual Environment and Web development using Django
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
ZFConf 2012: Capistrano для деплоймента PHP-приложений (Роман Лапин)
 
OpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid CloudOpenSource ToolChain for the Hybrid Cloud
OpenSource ToolChain for the Hybrid Cloud
 
2015 DockerCon Using Docker in production at bity.com
2015 DockerCon Using Docker in production at bity.com2015 DockerCon Using Docker in production at bity.com
2015 DockerCon Using Docker in production at bity.com
 
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
Assembling an Open Source Toolchain to Manage Public, Private and Hybrid Clou...
 
DockerCon EU 2015: Trading Bitcoin with Docker
DockerCon EU 2015: Trading Bitcoin with DockerDockerCon EU 2015: Trading Bitcoin with Docker
DockerCon EU 2015: Trading Bitcoin with Docker
 
Symfony Deployments on Heroku
Symfony Deployments on HerokuSymfony Deployments on Heroku
Symfony Deployments on Heroku
 
Hosting Your Own OTA Update Service
Hosting Your Own OTA Update ServiceHosting Your Own OTA Update Service
Hosting Your Own OTA Update Service
 
How I hack on puppet modules
How I hack on puppet modulesHow I hack on puppet modules
How I hack on puppet modules
 
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
From Arm to Z: Building, Shipping, and Running a Multi-platform Docker Swarm ...
 
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
A to Z of a Multi-platform Docker Swarm: Building, Shipping, and Running Mult...
 
Dockercon EU 2014
Dockercon EU 2014Dockercon EU 2014
Dockercon EU 2014
 
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
The Tale of a Docker-based Continuous Delivery Pipeline by Rafe Colton (ModCl...
 
Git::Hooks
Git::HooksGit::Hooks
Git::Hooks
 
From Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOSFrom Zero to Application Delivery with NixOS
From Zero to Application Delivery with NixOS
 
Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3Migrating Legacy Rails Apps to Rails 3
Migrating Legacy Rails Apps to Rails 3
 
Create ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm packageCreate ReactJS Component & publish as npm package
Create ReactJS Component & publish as npm package
 
Using Prometheus to monitor your build pipelines
Using Prometheus to monitor your build pipelinesUsing Prometheus to monitor your build pipelines
Using Prometheus to monitor your build pipelines
 

More from Ben Scheirman

Effective iOS Network Programming Techniques
Effective iOS Network Programming TechniquesEffective iOS Network Programming Techniques
Effective iOS Network Programming TechniquesBen Scheirman
 
Objective-C & iPhone for .NET Developers
Objective-C & iPhone for .NET DevelopersObjective-C & iPhone for .NET Developers
Objective-C & iPhone for .NET DevelopersBen Scheirman
 
iPhone for .NET Developers
iPhone for .NET DevelopersiPhone for .NET Developers
iPhone for .NET DevelopersBen Scheirman
 
Reasons To Love Ruby
Reasons To Love RubyReasons To Love Ruby
Reasons To Love RubyBen Scheirman
 

More from Ben Scheirman (6)

Meet Git
Meet GitMeet Git
Meet Git
 
Effective iOS Network Programming Techniques
Effective iOS Network Programming TechniquesEffective iOS Network Programming Techniques
Effective iOS Network Programming Techniques
 
Objective-C & iPhone for .NET Developers
Objective-C & iPhone for .NET DevelopersObjective-C & iPhone for .NET Developers
Objective-C & iPhone for .NET Developers
 
iPhone for .NET Developers
iPhone for .NET DevelopersiPhone for .NET Developers
iPhone for .NET Developers
 
SQLite Techniques
SQLite TechniquesSQLite Techniques
SQLite Techniques
 
Reasons To Love Ruby
Reasons To Love RubyReasons To Love Ruby
Reasons To Love Ruby
 

Recently uploaded

Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterMydbops
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Mark Goldstein
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024TopCSSGallery
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Nikki Chapple
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesKari Kakkonen
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfAarwolf Industries LLC
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...itnewsafrica
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch TuesdayIvanti
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPathCommunity
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentPim van der Noll
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Alkin Tezuysal
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI AgeCprime
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxfnnc6jmgwh
 

Recently uploaded (20)

Scale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL RouterScale your database traffic with Read & Write split using MySQL Router
Scale your database traffic with Read & Write split using MySQL Router
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
Arizona Broadband Policy Past, Present, and Future Presentation 3/25/24
 
Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024Top 10 Hubspot Development Companies in 2024
Top 10 Hubspot Development Companies in 2024
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
Microsoft 365 Copilot: How to boost your productivity with AI – Part one: Ado...
 
Testing tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examplesTesting tools and AI - ideas what to try with some tool examples
Testing tools and AI - ideas what to try with some tool examples
 
Landscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdfLandscape Catalogue 2024 Australia-1.pdf
Landscape Catalogue 2024 Australia-1.pdf
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...Zeshan Sattar- Assessing the skill requirements and industry expectations for...
Zeshan Sattar- Assessing the skill requirements and industry expectations for...
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
2024 April Patch Tuesday
2024 April Patch Tuesday2024 April Patch Tuesday
2024 April Patch Tuesday
 
Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
UiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to HeroUiPath Community: Communication Mining from Zero to Hero
UiPath Community: Communication Mining from Zero to Hero
 
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native developmentEmixa Mendix Meetup 11 April 2024 about Mendix Native development
Emixa Mendix Meetup 11 April 2024 about Mendix Native development
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
Unleashing Real-time Insights with ClickHouse_ Navigating the Landscape in 20...
 
A Framework for Development in the AI Age
A Framework for Development in the AI AgeA Framework for Development in the AI Age
A Framework for Development in the AI Age
 
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptxGenerative AI - Gitex v1Generative AI - Gitex v1.pptx
Generative AI - Gitex v1Generative AI - Gitex v1.pptx
 

A Scalable Rails App Deployed in 60 Seconds

  • 1. A Scalable Rails app Deployed in 60 seconds 1
  • 2. Ben Scheirman • Director of Development at ChaiONE • Microsoft MVP, ASP Insider • Certified ScrumMaster • Former .NET Ninja, now Rails/iPhone aficionado 2
  • 3. Ben Scheirman • ...not affiliated with Heroku 3
  • 4. So you have a fantastic app? 4
  • 5. 5
  • 6. 6
  • 7. 7
  • 8. 7
  • 9. 7
  • 10. 7
  • 11. 7
  • 12. 7
  • 13. 8
  • 14. 8
  • 15. 9
  • 16. 10
  • 17. 11
  • 18. x 1,000? 11
  • 19. 12
  • 20. x 10,000? 12
  • 22. writes reads x 1,000,000? 13
  • 23. 14
  • 24. On-Demand 15
  • 25. # Users by time of day 400 300 200 100 0 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM 16
  • 26. # Users by time of day 400 300 200 100 0 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM 16
  • 27. # Users by time of day 400 300 200 100 0 12 AM 3AM 6AM 9AM 12PM 3PM 6PM 9PM 12AM Only need massive scale from 9am - 9pm 16
  • 28. Expected Users For PR Campaign 900 675 450 225 0 Mar 1 Mar 15 Apr 1 Apr 15 May 1 May 15 Jun 1 Jun 2 17
  • 29. Expected Users For PR Campaign 900 675 450 225 0 Mar 1 Mar 15 Apr 1 Apr 15 May 1 May 15 Jun 1 Jun 2 17
  • 30. SCALE 18
  • 31. 19
  • 32. Awesome Shredder Art by Dan Barret 20
  • 33. gem install heroku Awesome Shredder Art by Dan Barret 20
  • 34. • Platform as a service for Rack-based apps • Scale easily • Great workflow • Free to start / Friendly Pricing • Complete command-line API 21
  • 35. Deploy a rails app in 5 steps git init git add . git commit -m “My First Commit” heroku create git push heroku master Creating morning-summer-18..... done Created http://morning-summer-18.heroku.com/ | git@heroku.com:morning-summer-18.git 22
  • 36. Deploy a rails app in 5 steps git init git add . git commit -m “My First Commit” heroku create git push heroku master Creating morning-summer-18..... done Created http://morning-summer-18.heroku.com/ | git@heroku.com:morning-summer-18.git LET THAT SOAK IN... 22
  • 37. Using git for deployment is f***ing GENIUS 23
  • 38. Technology • Amazon Web Services • Caching w/ Varnish • Debian Linux • Erlang Routing Mesh • Nginx • PostgreSQL 24
  • 39. 25
  • 41. How Heroku Scales or WTF is a Dyno? 26
  • 42. How Heroku Scales or WTF is a Dyno? 26
  • 43. How Heroku Scales or WTF is a Dyno? 26
  • 47. When to add dynos • Increasing response times • “Backlog Too Deep” Error 28
  • 48. Always Measure • New Relic RPM • Apache Bench 29
  • 49. Heroku Tips • Multiple Heroku apps for Test, Staging, Production • Learn the awesome-ness of Taps • Heroku logs • Heroku Console • Useful addons: New Relic, Exceptional 30
  • 50. Backups 31
  • 51. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 32
  • 52. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 33
  • 53. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 34
  • 54. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 35
  • 55. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 36
  • 56. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 37
  • 57. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 38
  • 58. Coping with the Free Single Bundle task :backup do bundle_name = "my-backup" heroku_app = ENV['app'] def wait_for_response_text(text) heroku_app = ENV['app'] #lame, I know begin puts "." bundles = `heroku bundles --app #{heroku_app}` end while bundles.match(text).nil? end #check for existing bundle bundles = `heroku bundles --app #{heroku_app}` unless bundles.match /has no bundles/ `heroku bundles:destroy #{bundle_name} --app #{heroku_app}` wait_for_response_text 'has no bundles' end puts "Capture bundle #{bundle_name}..." `heroku bundles:capture #{bundle_name} --app #{heroku_app}` wait_for_response_text "complete" puts "Downloading bundle..." `heroku bundles:download #{bundle_name} --app #{heroku_app}` timestamp = `date -u '+%Y-%m-%d-%H-%M'`.chomp new_path = "backups/#{heroku_app}-#{timestamp}.tar.gz" mkdir "backups" unless File.exists? "backups" `mv #{heroku_app}.tar.gz #{new_path}` puts "Bundle saved to #{new_path}" end end 39
  • 59. One-button Deployments task :deploy do heroku_app = ENV['app'] heroku_config = Hash.new Rake::Task["heroku:backup"].invoke puts "Turning maintenance on..." puts "** " + `heroku maintenance:on --app #{heroku_app}` sleep 15 #maintenance mode causes your slug to be recompiled puts "Pushing changes to heroku..." puts "** " + `git push #{git_remotes[heroku_app]} master` puts "Migrating heroku databases..." puts "** " + `heroku rake db:migrate --app #{heroku_app}` puts "Setting up config variables..." heroku_config.each_pair do |k, v| puts "** " + `heroku config:add #{k.to_s.upcase}=#{v}` end puts "Turning maintenance mode off" puts "** " + `heroku maintenance:off --app #{heroku_app}` puts "DEPLOYMENT DONE!" end 40
  • 61. Delayed Jobs def send_bulk_emails BulkEmailSender.send_a_ton flash[:notice] => "Ok we sent them" end 41
  • 62. Delayed Jobs def send_bulk_emails BulkEmailSender.send_a_ton flash[:notice] => "Ok we sent them" end def send_bulk_emails BulkEmailSender.send_later(:send_a_ton) flash[:notice] => "Ok we sent them" end 41
  • 64. Delayed Jobs > gem install delayed_job > rails g delayed_job > rake db:migrate 42
  • 65. Delayed Jobs > gem install delayed_job > rails g delayed_job > rake db:migrate > heroku workers 1 simple-snow-68 now running 1 worker > heroku workers +1 simple-snow-68 now running 2 workers 42
  • 67. Delayed Jobs $0.05 per hour / worker (even when it's not processing Jobs) 43
  • 68. Delayed Jobs $0.05 per hour / worker (even when it's not processing Jobs) http://github.com/pedro/delayed_job/commit/ 09d7657e1fc7d25072e6c5e73ede20d6e1185eac http://bit.ly/9Qokff 43
  • 69. Delayed Jobs Pedro's Fork / auto-scale branch 44
  • 70. Delayed Jobs Pedro's Fork / auto-scale branch //lib/delayed/job.rb def after_create Manager.scale_up if self.class.auto_scale && Manager.qty == 0 end //lib/delayed/worker.rb Manager.scale_down if count.zero? && Job.auto_scale && Job.count == 0 44
  • 71. • Read-only file system • some gems don’t work • File uploads? • Temp Directory • SSL, memcached, Full-text-search expensive • Bound-by Amazon’s SLA 45
  • 72. contact = { ! :blog => http://flux88.com, ! ! :twitter => @subdigital, ! ! :email => ben@scheirman.com } 46
  • 73. 47