cover of the paperback book
a generic e-reader showing the book's cover on it

Sustainable Web Development with Ruby on Rails

Over 450 Pages of Practical Tips for Building Rails Apps that Last


  • Tired of bloated models that won't stop growing?

  • Development slowed to a crawl due to ever-increasing complexity?

  • Bogged down by an ever-growing list of gems you think will solve your problems?

  • Determined that next time, you'll “do it right”?

This book can help.

Learn how to manage carrying costs
by strategically incurring opportunity costs

Buy Now and learn more of these tips. The book has extended examples and detailed, pragmatic explanations for when to use—or not use—each technique, all based on real-world experience.

What You Get

a generic e-reader showing the book's cover on it

Prefer it Print?

cover of the paperback book

Why no package on print and electronic? Due to the realities of self-publishing, I can't offer you a package deal on both the ebook and the print version. My recommendation is to buy the version that you find most comfortable for reading.


This book's guidance applies to generally any Rails or Ruby version, however the book is kept up to date with the latest versions.

See the CHANGELOG to understand the differences in each release of the book.

Technology Version
Rails 7.1
Ruby 3.2

This book's guidance applies to generally any Rails or Ruby version, however the book is kept up to date with the latest versions.


See the CHANGELOG to understand the differences in each release of the book.

International Pricing

I realize the cost of living outside the United States can be wildly different from living in the U.S. and that a $50 book can be a big investment. I have created several discount codes that will bring the price down to a level that's more in line with the purchasing power in your country.

It's not perfect, and you are on your honor to choose the best discount for where you live. Visit my website for more info and then use the best code at checkout for the eBook. If you are buying the print book from Amazon, I have adjusted the pricing in Amazon already, though Amazon only allows me to set pricing for certain countries.

portrait of david bryant copeland

About Me

portrait of david bryant copeland My name is David Bryant Copeland and I've spent the last ten years working on long-lived Rails apps. I've worked on a huge monolith whose construction was not managed as well as greenfield apps that evolved over many years from monoliths to a microservices architecture.

13 years prior to that I worked on various technologies and apps both for consulting clients and startups. Lastly, I've advised several startups using Rails and seen first-hand how small mistakes made early on can have a cascading effect on team sustainabilty.

The content of this book is based on my actual experience—I've really done everything in the book. I've seen (and made) decisions that both lead to great sustianbility as well as harmed it. There's nothing theoretical about what's in the book.

Feel free to look at my resume to see what my experience is. I've also authored several technical books, including Agile Web Development with Rails 6, The Senior Software Engineer, Ruby on Rails Background Jobs with Sidekiq, and SOLID is not Solid.

I go by “Dave” and am @davetron5000 on Mastodon. I love to talk Rails, cocktails, cats, and scuba.

Table of Contents

  1. Introduction
    1. Why This Book Exists
      1. What is Sustainability?
      2. Why Care About Sustainability?
      3. How to Value Sustainability
      4. Assumptions
      5. Opportunity and Carrying Costs
      6. Why should you trust me?
    2. The Rails Application Architecture
      1. Boundaries
      3. Models
      4. Everything Else
      5. The Pros and Cons of the Rails Application Architecture
      6. Where We Go From Here
    3. Following Along in This Book
      1. Typographic Conventions
      2. Software Versions
      3. Sample Code
    4. Start Your App Off Right
      1. Creating a Rails App
      2. Using The Environment for Runtime Configuration
      3. Configuring Local Development Environment with dotenv
      4. Automating Application Setup with bin/setup
      5. Running the Application Locally with bin/run
      6. Putting Tests and Other Quality Checks in bin/ci
      7. Improving Production Logging with lograge
    5. Business Logic (Does Not Go in Active Records)
      1. Business Logic Makes Your App Special…and Complex
      2. Bugs in Commonly-Used Classes Have Wide Effects
      3. Business Logic in Active Records Puts Churn and Complexity in Critical Classes
      4. Example Design of a Feature
  2. Deep Dive into Rails
    1. Routes and URLs
      1. Always Use Canonical Routes that Conform to Rails’ Defaults
      2. Never Configure Routes That Aren’t Being Used
      3. Vanity URLs Should Redirect to a Canonical Route
      4. Don’t Create Custom Actions, Create More Resources
      5. Use Nested Routes Strategically
      6. Nested Routes Can Organize Content Pages
    2. HTML Templates
      1. Use Semantic HTML
      2. Ideally, Expose One Instance Variable Per Action
      3. Think of Partials as Re-usable Components
      4. Just Use ERB
    3. Helpers
      1. Don’t Conflate Helpers with Your Domain
      2. Helpers are Best at Exposing Global UI State and Generating Markup
      3. Define Helpers in As Few Locations as Possible
      4. Presenters, Decorators, and View Models Have Their Own Problems
      5. Use Rails’ APIs to Generate Markup
      6. Helpers Should Be Tested and Thus Testable
    4. CSS
      1. Adopt a Design System
      2. Adopt a CSS Strategy
      3. Create a Living Style Guide to Document Your Design System and CSS Strategy
    5. Minimize JavaScript
      1. How and Why JavaScript is a Serious Liability
      2. Embrace Server-Rendered Rails Views
      3. Tweak Turbo to Provide a Slightly Better Experience
    6. Carefully Manage the JavaScript You Need
      1. Embrace Plain JavaScript for Basic Interactions
      2. Carefully Choose One Framework When You Need It
      3. Ensure System Tests Fail When JavaScript is Broken
    7. Testing the View
      1. Understand the Value and Cost of Tests
      2. Use :rack_test for non-JavaScript User Flows
      3. Test Against Default Markup and Content Initially
      4. Cultivate Explicit Diagnostic Tools to Debug Test Failures
      5. Fake The Back-end To Get System Tests Passing
      6. Use data-testid Attributes to Combat Brittle Tests
      7. Test JavaScript Interactions with a Real Browser
    8. Models, Part 1
      1. Active Record is for Database Access
      2. Active Model is for Resource Modeling
    9. The Database
      1. Logical and Physical Data Models
      2. Create a Logical Model to Build Consensus
      3. Planning the Physical Model to Enforce Correctness
      4. Creating Correct Migrations
      5. Writing Tests for Database Constraints
    10. Business Logic Code is a Seam
      1. Business Logic Code Must Reveal Behavior
      2. Services are Stateless, Explicitly-Named Classes with Explicitly-Named Methods
      3. Implementation Patterns You Might Want to Avoid
    11. Models, Part 2
      1. Validations Don’t Provide Data Integrity
      2. Validations Are Awesome For User Experience
      3. How to (Barely) Use Callbacks
      4. Scopes are Often Business Logic and Belong Elsewhere
      5. Model Testing Strategy
    12. End-to-End Example
      1. Example Requirements
      2. Building the UI First
      3. Writing a System Test
      4. Sketch Business Logic and Define the Seam
      5. Fully Implement and Test Business Logic
      6. Finished Implementation
      7. Reflecting on What We’ve Built
    13. Controllers
      1. Controller Code is Configuration
      2. Don’t Over-use Callbacks
      3. Controllers Should Convert Parameters to Richer Types
      4. Don’t Over Test
    14. Jobs
      1. Use Jobs To Defer Execution or Increase Fault-Tolerance
      2. Understand How Your Job Backend Works
      3. Sidekiq is The Best Job Backend for Most Teams
      4. Queue Jobs Directly, and Have Them Defer to Your Business Logic Code
      5. Job Testing Strategies
      6. Jobs Will Get Retried and Must Be Idempotent
    15. Other Boundary Classes
      1. Mailers
      2. Rake Tasks
      3. Mailboxes, Cables, and Active Storage
  3. Beyond Rails
    1. Authentication and Authorization
      1. When in Doubt Use Devise or OmniAuth
      2. Authorization and Role-based Access Controls
      3. Test Access Controls In System Tests
    2. API Endpoints
      1. Be Clear About What—and Who—Your API is For
      2. Write APIs the Same Way You Write Other Code
      3. Use the Simplest Authentication System You Can
      4. Use the Simplest Content Type You Can
      5. Just Put The Version in the URL
      6. Use .to_json to Create JSON
      7. Test API Endpoints
    3. Sustainable Process and Workflows
      1. Use Continuous Integration To Deploy
      2. Frequent Dependency Updates
      3. Leverage Generators and Templates over Documentation
      4. RubyGems and Railties Can Distribute Configuration
    4. Operations
      1. Why Observability Matters
      2. Monitor Business Outcomes
      3. Logging is Powerful
      4. Manage Unhandled Exceptions
      5. Measure Performance
      6. Managing Secrets, Keys, and Passwords
  4. Appendices
    1. Setting Up Docker for Local Development
      1. Installing Docker
      2. What is Docker?
      3. Creating a Docker Image to Work In
      4. Making Sure Everything Works
    2. Monoliths, Microservices, and Shared Databases
      1. Monoliths Get a Bad Rap
      2. Microservices Are Not a Panacea.
      3. Sharing a Database Is Viable
    3. Technical Leadership is Critical
      1. Leadership Is About Shared Values
      2. Leaders Can be Held Accountable
      3. Accountability Can be Implicit
    4. Colophon
Buy e-Book $49.95