Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Building, Deploying, and Monitoring Ruby Web Ap...

Building, Deploying, and Monitoring Ruby Web Applications with Falcon (Kaigi on Rails 2025)

Samuel Williams

October 09, 2025

Transcript

301 slides
  1. Value × Scope = Impact ৼΓฦΔͱɺ͜Ε͸୯ͳΔࣗ෼ͷෆຬͰ͸ͳ͘ɺRubyͦͷ΋ͷ ʹؔΘΔ͜ͱͩͱؾ͖ͮ·ͨ͠ɻ Do more with

    less Lot’s of Ruby users Worthwhile Effort গͳ͍ࢿݯͰଟ͘ RubyϢʔβʔଟ਺ Ձ஋͋Δ௅ઓ
  2. Value × Scope = Impact ฒߦॲཧ͸େ͖ͳՁ஋Λ΋ͨΒ͠·͢ʕʕޮ཰ΛߴΊɺ৽͍͠ ΞϓϦέʔγϣϯઃܭΛՄೳʹ͠·͢ɻ Do more with

    less Lot’s of Ruby users Worthwhile Effort গͳ͍ࢿݯͰଟ͘ RubyϢʔβʔଟ਺ Ձ஋͋Δ௅ઓ
  3. Value × Scope = Impact ͦͷείʔϓ͸ڊେͰ͢ʕʕRuby͸ੈքதͷ਺ඦສͷΞϓϦ έʔγϣϯͱ։ൃऀΛࢧ͍͑ͯ·͢ɻ Do more with

    less Lot’s of Ruby users Worthwhile Effort গͳ͍ࢿݯͰଟ͘ RubyϢʔβʔଟ਺ Ձ஋͋Δ௅ઓ
  4. In 2019, I gave a talk called “The Journey to

    One Million” 2019೥ʹʮThe Journey to One Millionʢ100ສ΁ͷಓͷΓʣʯ ͱ͍͏ߨԋΛߦ͍·ͨ͠ɻ
  5. At RubyWorld Conference 2019, I talked about climate change. RubyWorld

    Conference 2019Ͱɺ ؾީมಈʹ͍ͭͯߨԋ͠·ͨ͠ɻ
  6. Falcon is a web server that uses one fi ber

    per request. Falcon͸ɺϦΫΤετ͝ͱʹ1ͭͷFiberΛ࢖༻͢Δ΢Σϒαʔ όʔͰ͢ɻ
  7. I want you to replicate this success with con fi

    dence. ͜ͷ੒ޭΛࣗ৴Λ࣋ͬͯ࠶ݱͯ͠΄͍͠ͷͰ͢ɻ
  8. IO::Event KQueue, EPoll, URing Fiber::Scheduler Concurrent Execution Model IO #read

    #write #wait Thread #join Thread::Mutex #lock Thread::Queue #pop Addrinfo .getaddrinfo Process .wait Timeout .timeout Fiber#raise Error Handling Fiber#storage “Per-request” State Management IO::Buffer Zero-copy Memory I/O Native Coroutines (Also used for M:N threading) IO#timeout Safety Net
  9. Application ActiveSupport IsolatedExecutionState = : fi ber ActiveRecord #lease_connection ActionDispatch

    Streaming Response ActionCable Server Adapterization Async::Cable Async::WebSocket Async::Job Async::Redis Live
  10. = > Booting Falcon v0.52.0 = > Rails 8.0.2 application

    sta r ting in development http: / / localhost:3000 = > Run `bin/ r ails se r ve r - - help` fo r mo r e sta r tup options
  11. # conf i g/application. r b conf i g.active_ r

    eco r d.pe r manent_connection_checkout = :disallowed conf i g.active_suppo r t.isolation_level = :f i be r # O r di r ectly if not pa r t of a Rails application: ActiveReco r d.pe r manent_connection_checkout = :disallowed ActiveSuppo r t : : IsolatedExecutionState.isolation_level = :f i be r
  12. # conf i g/application. r b conf i g.active_ r

    eco r d.pe r manent_connection_checkout = :disallowed conf i g.active_suppo r t.isolation_level = :f i be r # O r di r ectly if not pa r t of a Rails application: ActiveReco r d.pe r manent_connection_checkout = :disallowed ActiveSuppo r t : : IsolatedExecutionState.isolation_level = :f i be r
  13. # conf i g/application. r b conf i g.active_ r

    eco r d.pe r manent_connection_checkout = :disallowed conf i g.active_suppo r t.isolation_level = :f i be r # O r di r ectly if not pa r t of a Rails application: ActiveReco r d.pe r manent_connection_checkout = :disallowed ActiveSuppo r t : : IsolatedExecutionState.isolation_level = :f i be r
  14. class Pizza < ActiveReco r d : : Base validates

    :name, p r esence: t r ue def cook!(du r ation = 0.001) update!(status: 'cooking') sleep(du r ation) update!(status: 'hot') end end r un do |env| r equest = Rack : : Request.new(env) pizza = Pizza.c r eate!(name: "Ma r ghe r ita", status: "cold") pizza.cook! [200, {"content - type" = > "application/json"}, [pizza.to_json]] end
  15. class Pizza < ActiveReco r d : : Base validates

    :name, p r esence: t r ue def cook!(du r ation = 0.001) update!(status: 'cooking') sleep(du r ation) update!(status: 'hot') end end r un do |env| r equest = Rack : : Request.new(env) pizza = Pizza.c r eate!(name: "Ma r ghe r ita", status: "cold") pizza.cook! [200, {"content - type" = > "application/json"}, [pizza.to_json]] end
  16. class Pizza < ActiveReco r d : : Base validates

    :name, p r esence: t r ue def cook!(du r ation = 0.001) update!(status: 'cooking') sleep(du r ation) update!(status: 'hot') end end r un do |env| r equest = Rack : : Request.new(env) pizza = Pizza.c r eate!(name: "Ma r ghe r ita", status: "cold") pizza.cook! [200, {"content - type" = > "application/json"}, [pizza.to_json]] end
  17. class Pizza < ActiveReco r d : : Base validates

    :name, p r esence: t r ue def cook!(du r ation = 0.001) update!(status: 'cooking') sleep(du r ation) update!(status: 'hot') end end r un do |env| r equest = Rack : : Request.new(env) pizza = Pizza.c r eate!(name: "Ma r ghe r ita", status: "cold") pizza.cook! [200, {"content - type" = > "application/json"}, [pizza.to_json]] end
  18. class Pizza < ActiveReco r d : : Base validates

    :name, p r esence: t r ue def cook!(du r ation = 0.001) update!(status: 'cooking') sleep(du r ation) update!(status: 'hot') end end r un do |env| r equest = Rack : : Request.new(env) pizza = Pizza.c r eate!(name: "Ma r ghe r ita", status: "cold") pizza.cook! [200, {"content - type" = > "application/json"}, [pizza.to_json]] end
  19. class Pizza < ActiveReco r d : : Base validates

    :name, p r esence: t r ue def cook!(du r ation = 0.001) update!(status: 'cooking') sleep(du r ation) update!(status: 'hot') end end r un do |env| r equest = Rack : : Request.new(env) pizza = Pizza.c r eate!(name: "Ma r ghe r ita", status: "cold") pizza.cook! [200, {"content - type" = > "application/json"}, [pizza.to_json]] end
  20. 4 workers, 3 threads (recommended default) Falcon vs Puma Requests/second

    0 1000 2000 3000 4000 Connection Count 1 4 40 Pum a F a lcon Pum a F a lcon Pum a F a lcon 3,232 461 166 1,231 456 165
  21. 4 workers, 10 threads Falcon vs Puma Requests/second 0 1500

    3000 4500 6000 Connection Count 40 80 160 Pum a F a lcon Pum a F a lcon Pum a F a lcon 5,341 4,779 3,232 2,214 2,241 2,223
  22. We need wrap the queue with the interface expected by

    ActiveJob. ActiveJob͕ظ଴͢ΔΠϯλʔϑΣʔεͰΩϡʔΛϥοϓ͢Δඞ ཁ͕͋Γ·͢ɻ
  23. Async::Job::Queue Job Data Job Data Enqueue Dequeue ActiveJob Seri a

    lize ActiveJob Deseri a lize Perform Now Perform L a ter
  24. It’s a nice design because we can directly execute the

    jobs. δϣϒΛ௚઀࣮ߦͰ͖ΔͷͰɺ༏Εͨઃܭʹͳ͍ͬͯ·͢ɻ
  25. module ActiveJob module QueueAdapte r s # = Sidekiq adapte

    r fo r Active Job class SidekiqAdapte r < Abst r actAdapte r def enqueue(job) # :nodoc: job.p r ovide r _job_id = JobW r appe r .set( w r apped: job.class, queue: job.queue_name ).pe r fo r m_async(job.se r ialize) end class JobW r appe r # :nodoc: include Sidekiq : : Wo r ke r def pe r fo r m(job_data) Base.execute job_data.me r ge("p r ovide r _job_id" = > jid) end end end end
  26. module ActiveJob module QueueAdapte r s # = Sidekiq adapte

    r fo r Active Job class SidekiqAdapte r < Abst r actAdapte r def enqueue(job) # :nodoc: job.p r ovide r _job_id = JobW r appe r .set( w r apped: job.class, queue: job.queue_name ).pe r fo r m_async(job.se r ialize) end class JobW r appe r # :nodoc: include Sidekiq : : Wo r ke r def pe r fo r m(job_data) Base.execute job_data.me r ge("p r ovide r _job_id" = > jid) end end end end
  27. module ActiveJob module QueueAdapte r s # = Sidekiq adapte

    r fo r Active Job class SidekiqAdapte r < Abst r actAdapte r def enqueue(job) # :nodoc: job.p r ovide r _job_id = JobW r appe r .set( w r apped: job.class, queue: job.queue_name ).pe r fo r m_async(job.se r ialize) end class JobW r appe r # :nodoc: include Sidekiq : : Wo r ke r def pe r fo r m(job_data) Base.execute job_data.me r ge("p r ovide r _job_id" = > jid) end end end end
  28. module Async module Job module Adapte r module ActiveJob #

    An executo r fo r p r ocessing jobs using `ActiveJob`. class Executo r # Initialize the executo r with an optional delegate. def initialize(delegate = nil) @delegate = delegate end # Execute a job with the given data. # @pa r amete r job_data [Hash] Se r ialized job data f r om ActiveJob. def execute(job_data) : : ActiveJob : : Callbacks. r un_callbacks(:execute) do job = : : ActiveJob : : Base.dese r ialize(job_data) begin job.pe r fo r m_now r escue = > e r r o r r r r r r
  29. # Initialize the executo r with an optional delegate. def

    initialize(delegate = nil) @delegate = delegate end # Execute a job with the given data. # @pa r amete r job_data [Hash] Se r ialized job data f r om ActiveJob. def execute(job_data) : : ActiveJob : : Callbacks. r un_callbacks(:execute) do job = : : ActiveJob : : Base.dese r ialize(job_data) begin job.pe r fo r m_now r escue = > e r r o r # Igno r e, as ActiveJob has al r eady logged the e r r o r . end end end
  30. # Initialize the executo r with an optional delegate. def

    initialize(delegate = nil) @delegate = delegate end # Execute a job with the given data. # @pa r amete r job_data [Hash] Se r ialized job data f r om ActiveJob. def execute(job_data) : : ActiveJob : : Callbacks. r un_callbacks(:execute) do job = : : ActiveJob : : Base.dese r ialize(job_data) begin job.pe r fo r m_now r escue = > e r r o r # Igno r e, as ActiveJob has al r eady logged the e r r o r . end end end
  31. # conf i g/initialize r s/async_job. r b Rails.application.conf i

    gu r e do conf i g.async_job.def i ne_queue "default" do enqueue Async : : Job : : P r ocesso r : : Agg r egate dequeue Async : : Job : : P r ocesso r : : Redis end conf i g.async_job.def i ne_queue "local" do dequeue Async : : Job : : P r ocesso r : : Inline end end
  32. # conf i g/initialize r s/async_job. r b Rails.application.conf i

    gu r e do conf i g.async_job.def i ne_queue "default" do enqueue Async : : Job : : P r ocesso r : : Agg r egate dequeue Async : : Job : : P r ocesso r : : Redis end conf i g.async_job.def i ne_queue "local" do dequeue Async : : Job : : P r ocesso r : : Inline end end
  33. # conf i g/initialize r s/async_job. r b Rails.application.conf i

    gu r e do conf i g.async_job.def i ne_queue "default" do enqueue Async : : Job : : P r ocesso r : : Agg r egate dequeue Async : : Job : : P r ocesso r : : Redis end conf i g.async_job.def i ne_queue "local" do dequeue Async : : Job : : P r ocesso r : : Inline end end
  34. class AsyncJobBenchma r kJob < ActiveJob : : Base self.queue_adapte

    r = :async_job queue_as :default def pe r fo r m sleep(0.001) end end
  35. class AsyncJobBenchma r kJob < ActiveJob : : Base self.queue_adapte

    r = :async_job queue_as :default def pe r fo r m sleep(0.001) end end
  36. class AsyncJobBenchma r kJob < ActiveJob : : Base self.queue_adapte

    r = :async_job queue_as :default def pe r fo r m sleep(0.001) end end
  37. 1 client, 1 worker, 1ms sleep per job. Sidekick vs

    Async::Job Jobs/second 0 7500 15000 22500 30000 Enqueue Dequeue Sidekiq Async::Job Sidekiq Async::Job 6,000 28,000 4,100 22,000
  38. class JobExecution < ApplicationReco r d afte r _c r

    eate_commit - > { b r oadcast_append_to "job_executions" } end
  39. class MyJob < ApplicationJob queue_as "default" def pe r fo

    r m(*a r guments) JobExecution.c r eate!(name: self.class.name, data: { a r guments: a r guments, }) end end
  40. class HomeCont r olle r < ApplicationCont r olle r

    def index @job_executions = JobExecution.all end def execute job = MyJob if queue = pa r ams[:queue] job = job.set(queue: queue) end job.pe r fo r m_late r (queued_to: queue) end end
  41. <h1>Async Job < / h1> <p>This is a simple example

    of how to use the async job gem. You can use the fo r m below to submit a job to the queue. The job will be executed in the backg r ound and the r esults will be displayed in the table below. < / p> <fo r m action="/execute" method="post"> <select name="queue"> <% Rails.application.conf i g.async_job.def i nitions.each do |name, _| %> <option value="<%= name %>"><%= name %> < / option> <% end %> < / select> <input type="submit" value="Submit" / > < / fo r m> <h2>Job Executions < / h2> <%= tu r bo_st r eam_f r om "job_executions" %> <table> <thead> r
  42. <h1>Async Job < / h1> <p>This is a simple example

    of how to use the async job gem. You can use the fo r m below to submit a job to the queue. The job will be executed in the backg r ound and the r esults will be displayed in the table below. < / p> <fo r m action="/execute" method="post"> <select name="queue"> <% Rails.application.conf i g.async_job.def i nitions.each do |name, _| %> <option value="<%= name %>"><%= name %> < / option> <% end %> < / select> <input type="submit" value="Submit" / > < / fo r m> <h2>Job Executions < / h2> <%= tu r bo_st r eam_f r om "job_executions" %> <table> <thead> r
  43. <% end %> < / select> <input type="submit" value="Submit" /

    > < / fo r m> <h2>Job Executions < / h2> <%= tu r bo_st r eam_f r om "job_executions" %> <table> <thead> <t r > <th>ID < / th> <th>Name < / th> <th>Data < / th> < / t r > < / thead> <tbody id="job_executions"> <%= r ende r @job_executions %> < / tbody> < / table>
  44. Successfully upg r aded to WebSocket (REQUEST_METHOD : GET, HTTP_CONNECTION

    : Upg r ade, HTTP_UPGRADE : websocket) Tu r bo : : St r eamsChannel is t r ansmitting the subsc r iption conf i r mation Tu r bo : : St r eamsChannel is st r eaming f r om job_executions
  45. Successfully upg r aded to WebSocket (REQUEST_METHOD : GET, HTTP_CONNECTION

    : Upg r ade, HTTP_UPGRADE : websocket) Tu r bo : : St r eamsChannel is t r ansmitting the subsc r iption conf i r mation Tu r bo : : St r eamsChannel is st r eaming f r om job_executions Sta r ted POST "/execute" fo r : : 1 at 2025-08-02 16 : 50 : 56 +1200 P r ocessing by HomeCont r olle r #execute as TURBO_STREAM Pa r amete r s: {"queue" = > "default"} [ActiveJob] Enqueued MyJob (Job ID : 069bf564-c358-4da8-b255-13be3051a112) to AsyncJob(default) with a r guments: {queued_to: "default"} [ActiveJob] ↳ app/cont r olle r s/home_cont r olle r . r b:13:in 'HomeCont r olle r #execute' No template found fo r HomeCont r olle r #execute, r ende r ing head :no_content Completed 204 No Content in 15ms (ActiveReco r d: 0.0ms (0 que r ies, 0 cached) | GC : 0.2ms) Tu r bo : : St r eamsChannel t r ansmitting "<tu r bo - st r eam action=\"append\" ta r get=\"job_executions\"><template><t r id=\"job_execution_1\">\n\t<td>1 < / td>\n\t<td>MyJob < / td>\n\t<td>{&quot;a r guments&quot; =&gt; [{&quot;queued_to&quot; =&gt; &quot;default&quot;}]} < / td>\n < / t r > < / template> < / tu r bo - st r eam>" (via st r eamed f r om job_executions)
  46. Successfully upg r aded to WebSocket (REQUEST_METHOD : GET, HTTP_CONNECTION

    : Upg r ade, HTTP_UPGRADE : websocket) Tu r bo : : St r eamsChannel is t r ansmitting the subsc r iption conf i r mation Tu r bo : : St r eamsChannel is st r eaming f r om job_executions Sta r ted POST "/execute" fo r : : 1 at 2025-08-02 16 : 50 : 56 +1200 P r ocessing by HomeCont r olle r #execute as TURBO_STREAM Pa r amete r s: {"queue" = > "default"} [ActiveJob] Enqueued MyJob (Job ID : 069bf564-c358-4da8-b255-13be3051a112) to AsyncJob(default) with a r guments: {queued_to: "default"} [ActiveJob] ↳ app/cont r olle r s/home_cont r olle r . r b:13:in 'HomeCont r olle r #execute' No template found fo r HomeCont r olle r #execute, r ende r ing head :no_content Completed 204 No Content in 15ms (ActiveReco r d: 0.0ms (0 que r ies, 0 cached) | GC : 0.2ms) Tu r bo : : St r eamsChannel t r ansmitting "<tu r bo - st r eam action=\"append\" ta r get=\"job_executions\"><template><t r id=\"job_execution_1\">\n\t<td>1 < / td>\n\t<td>MyJob < / td>\n\t<td>{&quot;a r guments&quot; =&gt; [{&quot;queued_to&quot; =&gt; &quot;default&quot;}]} < / td>\n < / t r > < / template> < / tu r bo - st r eam>" (via st r eamed f r om job_executions)
  47. Successfully upg r aded to WebSocket (REQUEST_METHOD : GET, HTTP_CONNECTION

    : Upg r ade, HTTP_UPGRADE : websocket) Tu r bo : : St r eamsChannel is t r ansmitting the subsc r iption conf i r mation Tu r bo : : St r eamsChannel is st r eaming f r om job_executions Sta r ted POST "/execute" fo r : : 1 at 2025-08-02 16 : 50 : 56 +1200 P r ocessing by HomeCont r olle r #execute as TURBO_STREAM Pa r amete r s: {"queue" = > "default"} [ActiveJob] Enqueued MyJob (Job ID : 069bf564-c358-4da8-b255-13be3051a112) to AsyncJob(default) with a r guments: {queued_to: "default"} [ActiveJob] ↳ app/cont r olle r s/home_cont r olle r . r b:13:in 'HomeCont r olle r #execute' No template found fo r HomeCont r olle r #execute, r ende r ing head :no_content Completed 204 No Content in 15ms (ActiveReco r d: 0.0ms (0 que r ies, 0 cached) | GC : 0.2ms) Tu r bo : : St r eamsChannel t r ansmitting "<tu r bo - st r eam action=\"append\" ta r get=\"job_executions\"><template><t r id=\"job_execution_1\">\n\t<td>1 < / td>\n\t<td>MyJob < / td>\n\t<td>{&quot;a r guments&quot; =&gt; [{&quot;queued_to&quot; =&gt; &quot;default&quot;}]} < / td>\n < / t r > < / template> < / tu r bo - st r eam>" (via st r eamed f r om job_executions)
  48. 1 process, 1000 clients, 20 broadcasts. ActionCable vs Async::Cable Mess

    a ges/second 0 20000 40000 60000 80000 Mess a ge ActionC a ble Async::C a ble 80,000 32,000
  49. class St r eamingCont r olle r < ApplicationCont r

    olle r def st r eam body = p r oc do |st r eam| 10.downto(1) do |i| st r eam.w r ite " # { i} bottles of bee r on the wall\n" sleep 1 st r eam.w r ite " # { i} bottles of bee r \n" sleep 1 st r eam.w r ite "Take one down, pass it a r ound\n" sleep 1 st r eam.w r ite " # { i - 1} bottles of bee r on the wall\n" sleep 1 end end self. r esponse = Rack : : Response[200, {"content - type" = > "text/plain"}, body] end end
  50. class St r eamingCont r olle r < ApplicationCont r

    olle r def st r eam body = p r oc do |st r eam| 10.downto(1) do |i| st r eam.w r ite " # { i} bottles of bee r on the wall\n" sleep 1 st r eam.w r ite " # { i} bottles of bee r \n" sleep 1 st r eam.w r ite "Take one down, pass it a r ound\n" sleep 1 st r eam.w r ite " # { i - 1} bottles of bee r on the wall\n" sleep 1 end end self. r esponse = Rack : : Response[200, {"content - type" = > "text/plain"}, body] end end
  51. class St r eamingCont r olle r < ApplicationCont r

    olle r def st r eam body = p r oc do |st r eam| 10.downto(1) do |i| st r eam.w r ite " # { i} bottles of bee r on the wall\n" sleep 1 st r eam.w r ite " # { i} bottles of bee r \n" sleep 1 st r eam.w r ite "Take one down, pass it a r ound\n" sleep 1 st r eam.w r ite " # { i - 1} bottles of bee r on the wall\n" sleep 1 end end self. r esponse = Rack : : Response[200, {"content - type" = > "text/plain"}, body] end end
  52. 10 bottles of bee r on the wall 10 bottles

    of bee r Take one down, pass it a r ound 9 bottles of bee r on the wall 9 bottles of bee r on the wall 9 bottles of bee r Take one down, pass it a r ound 8 bottles of bee r on the wall 8 bottles of bee r on the wall 8 bottles of bee r Take one down, pass it a r ound 7 bottles of bee r on the wall 7 bottles of bee r on the wall 7 bottles of bee r Take one down, pass it a r ound 6 bottles of bee r on the wall 6 bottles of bee r on the wall 6 bottles of bee r Take one down, pass it a r ound
  53. Summary Building with Falcon ✅ HTTP/2 + TLS with loc

    a lhost development certi f ic a tes.
  54. Summary Building with Falcon ✅ HTTP/2 + TLS with loc

    a lhost development certi f ic a tes. ✅ ActiveRecord fully supported (in f iber mode).
  55. Summary Building with Falcon ✅ HTTP/2 + TLS with loc

    a lhost development certi f ic a tes. ✅ ActiveRecord fully supported (in f iber mode). ✅ ActiveJob with Async support using Async::Job::Ad a pter::ActiveJob.
  56. Summary Building with Falcon ✅ HTTP/2 + TLS with loc

    a lhost development certi f ic a tes. ✅ ActiveRecord fully supported (in f iber mode). ✅ ActiveJob with Async support using Async::Job::Ad a pter::ActiveJob. ✅ ActionC a ble repl a ced by Async::C a ble for improved perform a nce a nd HTTP/2 WebSockets.
  57. Summary Building with Falcon ✅ HTTP/2 + TLS with loc

    a lhost development certi f ic a tes. ✅ ActiveRecord fully supported (in f iber mode). ✅ ActiveJob with Async support using Async::Job::Ad a pter::ActiveJob. ✅ ActionC a ble repl a ced by Async::C a ble for improved perform a nce a nd HTTP/2 WebSockets. ✅ Re a l-time Stre a ming a nd Inter a ctively using R a ck 3.
  58. # ! /us r /bin/env falcon - host # f

    r ozen_st r ing_lite r al: t r ue r equi r e "falcon/envi r onment/ r ack" r equi r e "falcon/envi r onment/lets_enc r ypt_tls" r equi r e "falcon/envi r onment/supe r viso r " se r vice " w w w .example.com" do include Falcon : : Envi r onment : : Rack include Falcon : : Envi r onment : : LetsEnc r yptTLS end
  59. # ! /us r /bin/env falcon - host # f

    r ozen_st r ing_lite r al: t r ue r equi r e "falcon/envi r onment/ r ack" r equi r e "falcon/envi r onment/lets_enc r ypt_tls" r equi r e "falcon/envi r onment/supe r viso r " se r vice " w w w .example.com" do include Falcon : : Envi r onment : : Rack include Falcon : : Envi r onment : : LetsEnc r yptTLS end
  60. # ! /us r /bin/env falcon - host # f

    r ozen_st r ing_lite r al: t r ue r equi r e "falcon/envi r onment/ r ack" r equi r e "falcon/envi r onment/lets_enc r ypt_tls" r equi r e "falcon/envi r onment/supe r viso r " se r vice " w w w .example.com" do include Falcon : : Envi r onment : : Rack include Falcon : : Envi r onment : : LetsEnc r yptTLS end
  61. # ! /us r /bin/env falcon - host # f

    r ozen_st r ing_lite r al: t r ue r equi r e "falcon/envi r onment/ r ack" r equi r e "falcon/envi r onment/lets_enc r ypt_tls" r equi r e "falcon/envi r onment/supe r viso r " se r vice " w w w .example.com" do include Falcon : : Envi r onment : : Rack include Falcon : : Envi r onment : : LetsEnc r yptTLS end
  62. > bundle exec ./falcon. r b 0.0s info: Falcon :

    : Command : : Host | Falcon Host v0.52.0 taking flight! | - Conf i gu r ation: ./falcon. r b | - To te r minate: Ct r l-C o r kill 87272 | - To r eload: kill -HUP 87272 0.07s info: Async : : Containe r : : Notify : : Console | {status: "Initializing cont r olle r . . . "} 0.07s info: Falcon : : Se r vice : : Se r ve r | Sta r ting w w w .example.com on #<Falcon : : P r oxyEndpoint p r otocol=Async : : HTTP : : P r otocol : : HTTP2 endpoint=unix:/Use r s/samuel/Develope r / socket r y/ w w w .example.com/application.ipc> 0.07s info: Async : : Se r vice : : Cont r olle r | Cont r olle r sta r ting . . . 0.58s info: Async : : Containe r : : Notify : : Console | { r eady: t r ue, size: 11} 0.59s info: Async : : Se r vice : : Cont r olle r | Cont r olle r sta r ted . . .
  63. > bundle exec ./falcon. r b 0.0s info: Falcon :

    : Command : : Host | Falcon Host v0.52.0 taking flight! | - Conf i gu r ation: ./falcon. r b | - To te r minate: Ct r l-C o r kill 87272 | - To r eload: kill -HUP 87272 0.07s info: Async : : Containe r : : Notify : : Console | {status: "Initializing cont r olle r . . . "} 0.07s info: Falcon : : Se r vice : : Se r ve r | Sta r ting w w w .example.com on #<Falcon : : P r oxyEndpoint p r otocol=Async : : HTTP : : P r otocol : : HTTP2 endpoint=unix:/Use r s/samuel/Develope r / socket r y/ w w w .example.com/application.ipc> 0.07s info: Async : : Se r vice : : Cont r olle r | Cont r olle r sta r ting . . . 0.58s info: Async : : Containe r : : Notify : : Console | { r eady: t r ue, size: 11} 0.59s info: Async : : Se r vice : : Cont r olle r | Cont r olle r sta r ted . . .
  64. # ! /us r /bin/env falcon - host # f

    r ozen_st r ing_lite r al: t r ue r equi r e "falcon/envi r onment/ r ack" r equi r e "falcon/envi r onment/lets_enc r ypt_tls" r equi r e "falcon/envi r onment/supe r viso r " se r vice " w w w .example.com" do include Falcon : : Envi r onment : : Rack po r t {ENV.fetch("PORT", 3000).to_i} endpoint {Async : : HTTP : : Endpoint.pa r se("http: / / localhost", po r t: po r t)} end
  65. # ! /us r /bin/env falcon - host # f

    r ozen_st r ing_lite r al: t r ue r equi r e "falcon/envi r onment/ r ack" r equi r e "falcon/envi r onment/lets_enc r ypt_tls" r equi r e "falcon/envi r onment/supe r viso r " se r vice " w w w .example.com" do include Falcon : : Envi r onment : : Rack po r t {ENV.fetch("PORT", 3000).to_i} endpoint {Async : : HTTP : : Endpoint.pa r se("http: / / localhost", po r t: po r t)} end
  66. > bundle exec ./falcon. r b 0.0s info: Falcon :

    : Command : : Host | Falcon Host v0.52.0 taking flight! | - Conf i gu r ation: ./falcon. r b | - To te r minate: Ct r l-C o r kill 87577 | - To r eload: kill -HUP 87577 0.07s info: Async : : Containe r : : Notify : : Console | {status: "Initializing cont r olle r . . . "} 0.07s info: Falcon : : Se r vice : : Se r ve r | Sta r ting w w w .example.com on #<Async : : HTTP : : Endpoint http: / / localhost:3000/ {po r t: 3000}> 0.07s info: Async : : Se r vice : : Cont r olle r | Cont r olle r sta r ting . . . 0.6s info: Async : : Containe r : : Notify : : Console | { r eady: t r ue, size: 11} 0.6s info: Async : : Se r vice : : Cont r olle r | Cont r olle r sta r ted . . .
  67. > bundle exec ./falcon. r b 0.0s info: Falcon :

    : Command : : Host | Falcon Host v0.52.0 taking flight! | - Conf i gu r ation: ./falcon. r b | - To te r minate: Ct r l-C o r kill 87577 | - To r eload: kill -HUP 87577 0.07s info: Async : : Containe r : : Notify : : Console | {status: "Initializing cont r olle r . . . "} 0.07s info: Falcon : : Se r vice : : Se r ve r | Sta r ting w w w .example.com on #<Async : : HTTP : : Endpoint http: / / localhost:3000/ {po r t: 3000}> 0.07s info: Async : : Se r vice : : Cont r olle r | Cont r olle r sta r ting . . . 0.6s info: Async : : Containe r : : Notify : : Console | { r eady: t r ue, size: 11} 0.6s info: Async : : Se r vice : : Cont r olle r | Cont r olle r sta r ted . . .
  68. # ! /us r /bin/env falcon - host # f

    r ozen_st r ing_lite r al: t r ue r equi r e "falcon/envi r onment/ r ack" r equi r e "falcon/envi r onment/lets_enc r ypt_tls" r equi r e "falcon/envi r onment/supe r viso r " se r vice " w w w .example.com" do include Falcon : : Envi r onment : : Rack include Falcon : : Envi r onment : : LetsEnc r yptTLS po r t {ENV.fetch("PORT", 3000).to_i} endpoint {Async : : HTTP : : Endpoint.pa r se("http: / / localhost", po r t: po r t)} end se r vice "backg r ound - jobs" do include Async : : Job : : Adapte r : : ActiveJob : : Envi r onment end
  69. # ! /us r /bin/env falcon - host # f

    r ozen_st r ing_lite r al: t r ue r equi r e "falcon/envi r onment/ r ack" r equi r e "falcon/envi r onment/lets_enc r ypt_tls" r equi r e "falcon/envi r onment/supe r viso r " se r vice " w w w .example.com" do include Falcon : : Envi r onment : : Rack include Falcon : : Envi r onment : : LetsEnc r yptTLS po r t {ENV.fetch("PORT", 3000).to_i} endpoint {Async : : HTTP : : Endpoint.pa r se("http: / / localhost", po r t: po r t)} end se r vice "backg r ound - jobs" do include Async : : Job : : Adapte r : : ActiveJob : : Envi r onment end
  70. > pst r ee 88602 -+= 88602 samuel r uby

    /Use r s/samuel/.gem/ r uby/3.4.5/bin/falcon - host ./falcon. r b | - - - 88603 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88604 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88605 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88606 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88607 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) | - - - 88608 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) | - - - 88609 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) \ - - - 88610 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local)
  71. > pst r ee 88602 -+= 88602 samuel r uby

    /Use r s/samuel/.gem/ r uby/3.4.5/bin/falcon - host ./falcon. r b | - - - 88603 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88604 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88605 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88606 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88607 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) | - - - 88608 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) | - - - 88609 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) \ - - - 88610 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local)
  72. > pst r ee 88602 -+= 88602 samuel r uby

    /Use r s/samuel/.gem/ r uby/3.4.5/bin/falcon - host ./falcon. r b | - - - 88603 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88604 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88605 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88606 samuel w w w .example.com (C=0/0 R=0/0 L=0.0) | - - - 88607 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) | - - - 88608 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) | - - - 88609 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local) \ - - - 88610 samuel backg r ound - jobs (default R=0 D=0 P=0/0, local)
  73. > falcon vi r tual /s r v/http/*/falcon. r b

    0.0s info: Falcon : : Command : : Vi r tual | Falcon Vi r tual v0.52.0 taking flight! | - Running on r uby 3.4.5 (2025-07-16 r evision 20cda200d3) +PRISM | - To te r minate: Ct r l-C o r kill 92831 | - To r eload all sites: kill -HUP 92831 . . .
  74. # /etc/systemd/system/falcon.se r vice [Unit] Desc r iption=Falcon Vi r

    tual Web Se r ve r Afte r =netwo r k.ta r get [Se r vice] Type=notify Envi r onment=VARIANT=p r oduction # Envi r onment=CONSOLE_LEVEL=debug ExecSta r t=/us r /bin/falcon vi r tual "/s r v/http/*/falcon. r b" [Install] WantedBy=multi - use r .ta r get
  75. # /etc/systemd/system/falcon.se r vice [Unit] Desc r iption=Falcon Vi r

    tual Web Se r ve r Afte r =netwo r k.ta r get [Se r vice] Type=notify Envi r onment=VARIANT=p r oduction # Envi r onment=CONSOLE_LEVEL=debug ExecSta r t=/us r /bin/falcon vi r tual "/s r v/http/*/falcon. r b" [Install] WantedBy=multi - use r .ta r get
  76. # /etc/systemd/system/falcon.se r vice [Unit] Desc r iption=Falcon Vi r

    tual Web Se r ve r Afte r =netwo r k.ta r get [Se r vice] Type=notify Envi r onment=VARIANT=p r oduction # Envi r onment=CONSOLE_LEVEL=debug ExecSta r t=/us r /bin/falcon vi r tual "/s r v/http/*/falcon. r b" [Install] WantedBy=multi - use r .ta r get
  77. containe r s: - name: my - app image: my

    - app - image:latest env: - name: NOTIFY_LOG value: "/tmp/notify.log" po r ts: - containe r Po r t: 9292 r eadinessP r obe: exec: command: ["bundle", "exec", "bake", "async:containe r :notify:log: r eady?"] initialDelaySeconds: 5 pe r iodSeconds: 5 failu r eTh r eshold: 12
  78. containe r s: - name: my - app image: my

    - app - image:latest env: - name: NOTIFY_LOG value: "/tmp/notify.log" po r ts: - containe r Po r t: 9292 r eadinessP r obe: exec: command: ["bundle", "exec", "bake", "async:containe r :notify:log: r eady?"] initialDelaySeconds: 5 pe r iodSeconds: 5 failu r eTh r eshold: 12
  79. containe r s: - name: my - app image: my

    - app - image:latest env: - name: NOTIFY_LOG value: "/tmp/notify.log" po r ts: - containe r Po r t: 9292 r eadinessP r obe: exec: command: ["bundle", "exec", "bake", "async:containe r :notify:log: r eady?"] initialDelaySeconds: 5 pe r iodSeconds: 5 failu r eTh r eshold: 12
  80. For liveness probe, application speci fi c is better. Liveness

    Probeʹ͸ɺΞϓϦέʔγϣϯݻ༗ͷ΋ͷΛ࢖͏ํ͕๬ ·͍͠Ͱ͢ɻ
  81. > cu r l https: / / localhost:3000/up <!DOCTYPE html><html><body

    style="backg r ound - colo r : g r een"> < / body> < / html>
  82. livenessP r obe: httpGet: path: /up po r t: 3000

    initialDelaySeconds: 10 pe r iodSeconds: 10 failu r eTh r eshold: 3
  83. Summary Deploying with Falcon ✅ B a sic hosting using

    falcon. r b service f iles. ✅ C a n support multiple services for simpli f ied deployment.
  84. Summary Deploying with Falcon ✅ B a sic hosting using

    falcon. r b service f iles. ✅ C a n support multiple services for simpli f ied deployment. ✅ Virtu a l hosting using multiple falcon. r b service f iles.
  85. Summary Deploying with Falcon ✅ B a sic hosting using

    falcon. r b service f iles. ✅ C a n support multiple services for simpli f ied deployment. ✅ Virtu a l hosting using multiple falcon. r b service f iles. ✅ Direct support for systemd + NOTIFY_SOCKET.
  86. Summary Deploying with Falcon ✅ B a sic hosting using

    falcon. r b service f iles. ✅ C a n support multiple services for simpli f ied deployment. ✅ Virtu a l hosting using multiple falcon. r b service f iles. ✅ Direct support for systemd + NOTIFY_SOCKET. ✅ Decent support for Kubernetes using re a diness probe + NOTIFY_LOG.
  87. 2.01s wa r n: Async : : Containe r :

    : Fo r ked | Child failed health check! | { | "child": { | "name": "SleepSe r vice", | "pid": 70187, | “status": null | }, | "age": 2.0107369998004287, | "health_check_timeout": 2 | } 2.02s e r r o r : Async : : Containe r : : Fo r ked | { | "status": "pid 70187 SIGKILL (signal 9)" | }
  88. se r vice “ w w w .example.com” do #

    . . . othe r conf i gu r ation . . . include Async : : Containe r : : Supe r viso r : : Supe r vised end se r vice "supe r viso r " do include Async : : Containe r : : Supe r viso r : : Envi r onment monito r s do [Async : : Containe r : : Supe r viso r : : Memo r yMonito r .new( # The inte r val at which to check fo r memo r y leaks. inte r val: 1, # The total size limit of all p r ocesses: maximum_size_limit: 1024 * 1024 * 400, # 400 MB )] end end
  89. se r vice “ w w w .example.com” do #

    . . . othe r conf i gu r ation . . . include Async : : Containe r : : Supe r viso r : : Supe r vised end se r vice "supe r viso r " do include Async : : Containe r : : Supe r viso r : : Envi r onment monito r s do [Async : : Containe r : : Supe r viso r : : Memo r yMonito r .new( # The inte r val at which to check fo r memo r y leaks. inte r val: 1, # The total size limit of all p r ocesses: maximum_size_limit: 1024 * 1024 * 400, # 400 MB )] end end
  90. se r vice “ w w w .example.com” do #

    . . . othe r conf i gu r ation . . . include Async : : Containe r : : Supe r viso r : : Supe r vised end se r vice "supe r viso r " do include Async : : Containe r : : Supe r viso r : : Envi r onment monito r s do [Async : : Containe r : : Supe r viso r : : Memo r yMonito r .new( # The inte r val at which to check fo r memo r y leaks. inte r val: 1, # The total size limit of all p r ocesses: maximum_size_limit: 1024 * 1024 * 400, # 400 MB )] end end
  91. se r vice “ w w w .example.com” do #

    . . . othe r conf i gu r ation . . . include Async : : Containe r : : Supe r viso r : : Supe r vised end se r vice "supe r viso r " do include Async : : Containe r : : Supe r viso r : : Envi r onment monito r s do [Async : : Containe r : : Supe r viso r : : Memo r yMonito r .new( # The inte r val at which to check fo r memo r y leaks. inte r val: 1, # The total size limit of all p r ocesses: maximum_size_limit: 1024 * 1024 * 400, # 400 MB )] end end
  92. 4.07s e r r o r : Async : :

    Containe r : : Supe r viso r : : Memo r yMonito r | Memo r y leak detected in p r ocess: | { | "p r ocess_id": 68020, | "monito r ": { | "p r ocess_id": 68020, | "cu r r ent_size": 453509120, | "maximum_size": null, | "maximum_size_limit": 419430400, | "th r eshold_size": 10485760, | "inc r ease_count": 0, | "inc r ease_limit": 20 | } | }
  93. r equi r e 't r aces' class MyClass def

    my_method puts "Hello Wo r ld" end end # If t r acing is disabled, this is a no - op. T r aces : : P r ovide r (MyClass) do def my_method att r ibutes = { 'foo' = > 'ba r ' } T r aces.t r ace('my_method', att r ibutes: att r ibutes) do supe r end end end MyClass.new.my_method
  94. r equi r e 't r aces' class MyClass def

    my_method puts "Hello Wo r ld" end end # If t r acing is disabled, this is a no - op. T r aces : : P r ovide r (MyClass) do def my_method att r ibutes = { 'foo' = > 'ba r ' } T r aces.t r ace('my_method', att r ibutes: att r ibutes) do supe r end end end MyClass.new.my_method
  95. r equi r e 't r aces' class MyClass def

    my_method puts "Hello Wo r ld" end end # If t r acing is disabled, this is a no - op. T r aces : : P r ovide r (MyClass) do def my_method att r ibutes = { 'foo' = > 'ba r ' } T r aces.t r ace('my_method', att r ibutes: att r ibutes) do supe r end end end MyClass.new.my_method
  96. r equi r e 't r aces' class MyClass def

    my_method puts "Hello Wo r ld" end end # If t r acing is disabled, this is a no - op. T r aces : : P r ovide r (MyClass) do def my_method att r ibutes = { 'foo' = > 'ba r ' } T r aces.t r ace('my_method', att r ibutes: att r ibutes) do supe r end end end MyClass.new.my_method
  97. > bundle exec bake t r aces:p r ovide r

    :list output - - fo r mat json { "async": [ "t r aces/p r ovide r /async/ba r r ie r . r b", "t r aces/p r ovide r /async/task. r b", "t r aces/p r ovide r /async. r b" ], "async - pool": [ "t r aces/p r ovide r /async/pool/cont r olle r . r b" ], "p r otocol - http2": [ "t r aces/p r ovide r /p r otocol/http2/f r ame r . r b", "t r aces/p r ovide r /p r otocol/http2. r b" ] }
  98. # conf i g/t r aces. r b def p

    r epa r e # Add HTTP/2 p r otocol t r aces: r equi r e "t r aces/p r ovide r /p r otocol/http2" end
  99. r equi r e 'met r ics' class MyClass def

    self.my_method puts "Hello Wo r ld" end end Met r ics : : P r ovide r (MyClass.singleton_class) do CALL_COUNT = Met r ics.met r ic('call_count', :counte r ) def my_method CALL_COUNT.emit(1) supe r end end MyClass.my_method
  100. r equi r e 'met r ics' class MyClass def

    self.my_method puts "Hello Wo r ld" end end Met r ics : : P r ovide r (MyClass.singleton_class) do CALL_COUNT = Met r ics.met r ic('call_count', :counte r ) def my_method CALL_COUNT.emit(1) supe r end end MyClass.my_method
  101. r equi r e 'met r ics' class MyClass def

    self.my_method puts "Hello Wo r ld" end end Met r ics : : P r ovide r (MyClass.singleton_class) do CALL_COUNT = Met r ics.met r ic('call_count', :counte r ) def my_method CALL_COUNT.emit(1) supe r end end MyClass.my_method
  102. r equi r e 'met r ics' class MyClass def

    self.my_method puts "Hello Wo r ld" end end Met r ics : : P r ovide r (MyClass.singleton_class) do CALL_COUNT = Met r ics.met r ic('call_count', :counte r ) def my_method CALL_COUNT.emit(1) supe r end end MyClass.my_method
  103. > bundle exec bake met r ics:p r ovide r

    :list output - - fo r mat json { "async": [ "met r ics/p r ovide r /async/task. r b", "met r ics/p r ovide r /async. r b" ], "async - http": [ "met r ics/p r ovide r /async/http/client. r b", "met r ics/p r ovide r /async/http/se r ve r . r b", "met r ics/p r ovide r /async/http. r b" ], "async - containe r ": [ "met r ics/p r ovide r /async/containe r /gene r ic. r b", "met r ics/p r ovide r /async/containe r . r b" ] }
  104. # conf i g/met r ics. r b def p

    r epa r e # Add HTTP client and se r ve r met r ics: r equi r e "met r ics/p r ovide r /async/http" end
  105. Pro fi ler Traces Metrics Did something go wrong? Wh

    a t f a iled? How did it f a il? More Det a il Less Det a il
  106. Bigger Overhe a d More D a t a Sm

    a ller Overhe a d Less D a t a Pro fi ler Traces Metrics Did something go wrong? Wh a t f a iled? How did it f a il? More Det a il Less Det a il
  107. Console.info(self, "Hello Wo r ld", st r uctu r ed:

    "data") Subject Mess a ge Structured D a t a
  108. r equi r e "console" Console.info(self, "Hello Wo r ld",

    st r uctu r ed: "data") Console.debug(self, "Debugging info r mation", session: r equest.session) Console.wa r n(self, "This is a wa r ning") Console.e r r o r (self, "An e r r o r occu r r ed", exception: e r r o r ) Console.fatal(self, "A fatal e r r o r occu r r ed", exception: e r r o r )
  109. # conf i g/console. r b def make_output(io = nil,

    env = ENV, * * options) r equi r e "console/output/datadog" Console : : Output : : Datadog.new(supe r ) r escue LoadE r r o r supe r end
  110. 23.18s info: p r ocess_action.action_cont r olle r : Incoming

    r equest: GET "/". | { | "cont r olle r ": "WelcomeCont r olle r ", | "action": "index", | "fo r mat": "html", | "method": "GET", | "path": "/", | "status": 200, | "view_ r untime": 33.49500012397766, | "db_ r untime": 0.0, | "que r ies_count": 0, | "cached_que r ies_count": 0, | "sou r ce_add r ess": " : : 1", | "allocations": 60143, | "du r ation": 36.60800004005432 | }
  111. Summary Monitoring with Falcon ✅ Autom a tic he a

    lth checks detect h a ngs a nd st a lls.
  112. Summary Monitoring with Falcon ✅ Autom a tic he a

    lth checks detect h a ngs a nd st a lls. ✅ Supervisor fr a mework c a n monitor memory us a ge + custom monitors.
  113. Summary Monitoring with Falcon ✅ Autom a tic he a

    lth checks detect h a ngs a nd st a lls. ✅ Supervisor fr a mework c a n monitor memory us a ge + custom monitors. ✅ Flexible a pplic a tion tr a cing + distributed tr a cing.
  114. Summary Monitoring with Falcon ✅ Autom a tic he a

    lth checks detect h a ngs a nd st a lls. ✅ Supervisor fr a mework c a n monitor memory us a ge + custom monitors. ✅ Flexible a pplic a tion tr a cing + distributed tr a cing. ✅ Flexible a pplic a tion metrics.
  115. Summary Monitoring with Falcon ✅ Autom a tic he a

    lth checks detect h a ngs a nd st a lls. ✅ Supervisor fr a mework c a n monitor memory us a ge + custom monitors. ✅ Flexible a pplic a tion tr a cing + distributed tr a cing. ✅ Flexible a pplic a tion metrics. ✅ Logging with tr a ce correl a tion a nd f lexible processing.
  116. Includes many of the things we talked about by default.

    σϑΥϧτͰɺ͜Ε·Ͱʹ࿩ͨ͠ଟ͘ͷ͜ͱΛؚΜͰ͍·͢ɻ
  117. > bundle exec bake agent:context:install Installed context f r om

    17 gems: agent - context io - event met r ics t r aces async p r otocol - http p r otocol - http1 p r otocol - http2 async - se r vice bake - gem bake - r eleases cove r ed decode falcon sus sus - f i xtu r es - console utopia - p r oject
  118. Claude, consult agents.md and update my application to use falcon.

    Claudeɺagents.mdΛࢀরͯ͠ɺΞϓϦέʔγϣϯΛFalconର Ԡʹߋ৽͍ͯͩ͘͠͞ɻ
  119. Let’s take Ruby to the next level with Async, Falcon

    and Rails. AsyncɺFalconɺRailsͰRubyΛ࣍ͷϨϕϧ΁ɻ
  120. ΋ ͪ Ζ Μ Φ Ψ χ Ϋ ͳ ํ

    ๏ ΋ ͋ Γ · ͢

More Decks by Samuel Williams

Other Decks in Programming