rails/rails
Request lifecycle
How an incoming HTTP request becomes a response in Rails. This page traces the request through Rack, the middleware stack, the router, the controller, the view, and back.
End-to-end view
sequenceDiagram
participant Browser
participant Server as Web server (Puma)
participant App as Rails::Application
participant MW as Middleware stack
participant Router as ActionDispatch::Routing::RouteSet
participant Ctrl as Controller
participant Model as ActiveRecord
participant View as ActionView
Browser->>Server: HTTP/1.1 GET /posts
Server->>App: env hash (Rack)
App->>MW: call(env)
MW->>Router: env after middlewares
Router->>Ctrl: ControllerClass.action(:index).call(env)
Ctrl->>Model: Post.all
Model-->>Ctrl: relation/records
Ctrl->>View: render :index
View-->>Ctrl: rendered HTML
Ctrl-->>MW: [200, headers, body]
MW-->>App: response
App-->>Server: response
Server-->>Browser: HTTP response1. Rack and the application
The web server (Puma, Unicorn, Falcon) hands every request to Rails.application.call(env). Rails::Application is itself a Rack app — it inherits from Rails::Engine, which composes the middleware stack and the route set into a single Rack-compatible callable.
The entry point is Rails::Engine#call, defined in railties/lib/rails/engine.rb. It delegates to the built middleware stack at app.
2. Middleware stack
The default middleware stack is built by railties/lib/rails/application/default_middleware_stack.rb and lives in Rails.application.config.middleware. To inspect it in an app:
bin/rails middlewareTypical default order (top runs first):
ActionDispatch::HostAuthorization— protect against DNS rebinding.Rack::Sendfile—X-Sendfilesupport.ActionDispatch::Static— serve files frompublic/(only ifconfig.public_file_server.enabled).ActionDispatch::Executor— wrap the request inRails.application.executor.ActiveSupport::Cache::Strategy::LocalCache::Middleware— local cache scope.Rack::Runtime—X-Runtimeheader.Rack::MethodOverride—_methodparameter.ActionDispatch::RequestId— generate or readX-Request-Id.ActionDispatch::RemoteIp— setrequest.remote_ipthrough trusted proxies.Sprockets::Rails::QuietAssets— silence asset logs.Rails::Rack::Logger— request logging.ActionDispatch::ShowExceptions— convert exceptions to error pages.ActionDispatch::DebugExceptions— interactive web console / verbose errors in dev.ActionDispatch::ActionableExceptions— buttons in error pages to apply suggested fixes.ActionDispatch::Reloader— wrap withActiveSupport::Reloaderin dev.ActionDispatch::Callbacks—before/afterrequest callbacks.ActiveRecord::Migration::CheckPending— error in dev if migrations are pending.ActionDispatch::Cookies— populaterequest.cookie_jar.ActionDispatch::Session::CookieStore— populaterequest.session.ActionDispatch::Flash— flash hash.ActionDispatch::ContentSecurityPolicy::Middleware— assemble CSP headers.ActionDispatch::PermissionsPolicy::Middleware— feature-policy headers.Rack::Head— convert HEAD to GET internally.Rack::ConditionalGet—If-Modified-Since/If-None-Match.Rack::ETag— auto ETag.Rack::TempfileReaper— clean upTempfiles after the request.
After the stack, the request reaches Rails.application.routes — the route set.
3. Routing
config/routes.rb is evaluated against ActionDispatch::Routing::Mapper. The mapper builds a Journey::Routes collection inside the RouteSet:
actionpack/lib/action_dispatch/routing/route_set.rbactionpack/lib/action_dispatch/routing/mapper.rbactionpack/lib/action_dispatch/journey/
At request time, RouteSet#call matches the path and HTTP method against the journey AST and dispatches to a controller via ControllerClass.action(:name).call(env).
4. Controller dispatch
Action Controller wraps the action invocation in callbacks, parameters, rendering, and instrumentation:
graph TD
A[Controller.action :index] --> B[new instance]
B --> C[before_action filters]
C --> D{action_method}
D --> E[implicit render]
E --> F[after_action filters]
F --> G[ActiveSupport::Notifications.instrument 'process_action.action_controller']
G --> H[respond as Rack triple]The action method runs business logic, possibly:
- Querying models (
Post.where(...)). - Setting instance variables for the view.
- Issuing redirects, sending files, rendering JSON.
Controllers compose features by mixing in modules from actionpack/lib/action_controller/metal/. See packages/action-pack.
5. Model layer
ActiveRecord::Base.connection returns a connection from the per-thread connection pool. Queries flow through ActiveRecord::Relation (activerecord/lib/active_record/relation.rb) and QueryMethods (activerecord/lib/active_record/relation/query_methods.rb), then through Arel into the connection adapter.
The query_cache middleware (registered earlier) caches identical SQL within a single request.
For model-side details see packages/active-record.
6. View rendering
When the action calls render (or implicitly renders the action template), Action View takes over:
graph LR
A[render :index] --> B[LookupContext finds template]
B --> C[Template handler compiles]
C --> D[OutputBuffer collects]
D --> E[Layouts wrap output]
E --> F[String response body]actionview/lib/action_view/lookup_context.rb— search paths, formats, locales, variants.actionview/lib/action_view/template.rb— wraps a compiled method.actionview/lib/action_view/template/handlers/— ERB, Builder, Raw.actionview/lib/action_view/renderer/template_renderer.rb— drives rendering.actionview/lib/action_view/layouts.rb— layout resolution.
Helpers (actionview/lib/action_view/helpers/) are mixed into the view context. form_with consumes ActiveModel::Naming and ActiveModel::Errors to build forms and error displays.
For more, see packages/action-view.
7. Response back through the stack
The controller returns [status, headers, body]. The middleware stack runs in reverse on the way out:
Rack::ETagcomputes the ETag.ActionDispatch::ContentSecurityPolicy::Middlewareadds CSP headers.ActionDispatch::Cookieswrites any modified cookies intoSet-Cookie.Rails::Rack::Loggeremits the log line.ActionDispatch::Executorcleans up the per-request executor scope (releases connections, runsafter_callhooks).
Finally Rack writes the response to the socket.
Instrumentation
Throughout the request, ActiveSupport::Notifications events fire:
start_processing.action_controller,process_action.action_controllersql.active_recordcache_read.active_support,cache_write.active_supportrender_template.action_view,render_partial.action_view,render_collection.action_view
Subscribers in each component's log_subscriber.rb translate them into the familiar Started GET "/posts" ... log line.
Related pages
- packages/action-pack
- packages/action-view
- packages/active-record
- features/initialization-and-railties — what set the app up for the request to reach.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.