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)

Avatar for Samuel Williams

Samuel Williams

October 09, 2025
Tweet

Other Decks in Programming

Transcript

  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. ΋ ͪ Ζ Μ Φ Ψ χ Ϋ ͳ ํ

    ๏ ΋ ͋ Γ · ͢