Sustainable Web Development

with Ruby on Rails

Practical Tips for Building Web Applications that Last

A Book by David Bryant Copeland

Current Status as of 2020-08-02:
Pretty much done!!! Last chapter is on more advanced sustainability patterns. Buy now at the low beta price! The published price will go up!
What's inside?
Buy Beta Now $29.95

I will be releasing new chapters on a regular basis. If you purchase the beta, you will be notified via email when new versions are available. If you have purchased the beta and have feedback, please use this form.


  1. 🏆
    Pretty much done!!! Last chapter is on more advanced sustainability patterns. Buy now at the low beta price! The published price will go up!
  2. 🕸
    New chapter on JSON APIs in your Rails app. Buy now at the low beta price! Note that…I'm almost done!!
  3. 💪
    New chapter on operations and concerns around observability with your Rails app. Buy now at the low beta price! Note that…I'm almost done!!
  4. 📧
    Two MORE new chapters! One on other boundary classes (mailers, rake tasks) and one on sustainable workflows and processes. Buy now at the low beta price!
  5. 🔐
    Two new chapters! One on authentication/authorization and another on background jobs. Buy now at the low beta price!
  6. ✊🏿
    50% of all profits to be donated to support #BlackLivesMatter and the ongoing protests against police brutality in the United States.
  7. 🎛
    New chapter on controllers, plus some revisions on the end-to-end example, namely showing the full TDD/implementation cycle of the entire feature. Buy now at the low beta price!
  8. 👩‍🏫
    New chapter with an end-to-end example. This shows the process of building a UI, writing a system test, and managing business logic. It brings together everything in the book up to this point. Buy now at the low beta price!
  9. 💅
    New chapter: Models, Part 2, which covers validations, scopes, and the dreaded callback. Also a big thanks to Sean Miller for identifying tons of typos and areas lacking clarity. Additionally, I rescinded the guidance to just remove Turbolinks. My main concern about it was remediated—probably a long time ago—so this part is updated to reflect a different approach. Buy now at the low beta price!
  10. 🕴
    The business logic code chapter is ready. Buy now at the low beta price!
  11. 🖥
    New chapter on database design and modeling. Buy now at the low beta price!
  12. 🏋️‍♂️
    First Beta update with a new chapter on Models. Buy now at an introductory low price!
  13. 🚀
    Beta release! Buy now at an introductory lower price!
  14. 📝
    Updated TOC with the sections for rest of the view plus improved future sections
  15. 📝
    Updated TOC with the sections for the CSS chapter
  16. 📕
    Posted a draft of Chapter 1, which outlines the purpose and motivation for the book.
  17. 📝
    Posted a draft Outline
  18. 🚀
    Created the site.

Table of Contents


Got feedback?

  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. Setting Up For This Book
    1. What You’ll Need To Follow Along
    2. Setting up Docker for Local Development
  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 is What 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
  6. The View Layer
  7. 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. Be Wary of Nested Routes
  8. HTML Templates
    1. Use Semantic HTML
    2. Build Templates Around Their Controller’s Resource as a Single Instance Variable
    3. Think of Partials as Re-usable Components
    4. Just Use ERB
  9. Helpers
    1. Don’t Conflate Helpers with Your Domain
    2. Helpers Are Best At Markup and Formatting
    3. Presenters, Decorators, and View Models Have Their Own Problems
    4. Use Rails’ APIs to Generate Markup
    5. Helpers Should Be Tested and Thus Testable
  10. 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
  11. Minimize JavaScript
    1. How and Why JavaScript is a Serious Liability
    2. Embrace Server-Rendered Rails Views
    3. Disable Remote-Forms-By-Default and Tweak Turbolinks
  12. Carefully Manage the JavaScript You Need
    1. Embrace Plain JavaScript for Basic Interactions
    2. Carefully Choose One Framework When You Need It
    3. Unit Test As Much of Your JavaScript as You Can
  13. 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. Test JavaScript Interactions with a Real Browser
  14. Models, Part 1
    1. Active Record is for Database Access
    2. Active Model is for Resource Modeling
  15. 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
  16. Business Logic Code Should Be Thought of as a Seam
    1. Business Logic Code Must Reveal Behavior
    2. Services are Stateless, Explicitly-Named Classes with Explicitly-Named Methods
    3. Alternate Implementation Patterns You Might Want to Avoid
  17. 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
  18. 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
  19. Controllers
    1. Controller Code Should be Thought of as Configuration
    2. Don’t Over-use Callbacks
    3. Controllers Often Convert Parameters to Richer Types
    4. Don’t Over Test
  20. 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
  21. 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
  22. Other Boundary Classes
    1. Mailers
    2. Rake Tasks
    3. Mailboxes, Cables, and Active Storage
  23. 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 Shared Configuration
  24. 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
  25. API Endpoints
    1. Be Clear About What your API is For and Who Will Consume It
    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
  26. Sustainability As You Grow
    1. Database Transactions
    2. Sequenced Background Jobs, AKA Sagas
    3. Asynchronous Transaction
    4. Monoliths, Microservices, and Shared Databases
    5. Technical Leadership is Critical
    6. The End!
🚧 Beta Currently Stops Here 🚧

Email me some feedback