Build on Rails

Build internal tools on Rails

Every product is secretly two apps: the one your customers see, and the internal one your team runs it from. Avo builds that second app on the Rails models you already have, so you maintain one codebase instead of two.

250+ paying companies · 2.7M downloads of the avo gem

01

01 · the hand-built version

What building internal tools by hand actually costs

Internal tools rarely get planned. They accrete, one urgent screen at a time, until your team depends on a back office nobody owns and nobody wants to touch.

  • 01

    You are quietly building two apps

    Every feature you ship to customers spawns internal work behind it: refunds, plan changes, impersonation, moderation, support lookups. That second app has no roadmap and no budget, but your team cannot operate without it.

  • 02

    Support and ops are blocked on engineers

    With no tooling, 'can you change this for a customer' becomes a console session or a one-off script every time. Your developers become a manual API for the rest of the company, and real work stalls.

  • 03

    The admin sprawls into a dozen half-built screens

    Each team bolts on its own page with its own conventions. Nothing is consistent, nothing is documented, and onboarding a new developer to the internal app takes as long as onboarding them to the product.

  • 04

    It is your softest security target

    Internal tools hold the keys to everything: full data access and the power to change anything, often behind auth someone wrote in a hurry. A DIY admin is one of the riskiest things in your stack to get wrong.

02

02 · the Avo version

Your models are already the hard part. Avo is the rest.

Internal tools stop being side projects when they all share one framework inside your app. Describe a resource for each model and Avo renders the screens, search, filters, and actions your team needs. Whether the tool is a <a href="/rails-crm">CRM</a>, an <a href="/rails-inventory-app">inventory app</a>, a <a href="/rails-dashboard">metrics dashboard</a>, or a <a href="/rails-cms">CMS</a>, it is the same resources in the same app, sharing one set of conventions. Support tooling, ops dashboards, and the back office stop being separate side projects.

Every model becomes a screen

One resource file turns an Active Record model into a full CRUD interface with index, show, and forms. Your whole domain becomes navigable without writing controllers or views. See https://docs.avohq.io/4.0/resources.html.

The operational verbs, as buttons

Actions turn 'issue refund', 'extend trial', or 'suspend account' into one-click operations that run on one record or many at once, so support fixes things itself instead of filing a ticket to engineering.

Find any record in seconds

Search, filters, and scopes let anyone jump to the right customer or order without SQL. The lists your team lives in come from one resource definition, not a pile of bespoke pages.

One mental model across every tool

Because every tool is an Avo resource, they all look and behave the same. Any Rails developer who knows Avo is productive on your internal app on day one, so the knowledge lives in the framework, not in one person's head.

The right access for each team

Pundit-style policies decide who sees and does what, so support, finance, and ops each get exactly their slice. See https://docs.avohq.io/4.0/authorization.html.

Your whole team, one price

Avo is priced per app with unlimited users, so adding support, ops, and finance to your internal tools does not scale the bill with headcount.

A back-office Account resource, the whole file:

class Avo::Resources::Account < Avo::BaseResource
  self.title = :name
  self.includes = [:owner]

  def fields
    field :id, as: :id
    field :name, as: :text, required: true
    field :plan, as: :select, enum: ::Account.plans
    field :status, as: :badge, enum: ::Account.statuses
    field :mrr, as: :money
    field :trial_ends_at, as: :date_time
    field :owner, as: :belongs_to
    field :users, as: :has_many
    field :created_at, as: :date_time, hide_on: :forms
  end
end
03

03 · the timeline

From first resource to the team running on it

Hour one

Drop the avo gem in the Gemfile, mount the engine, and generate resources for your core models: accounts, users, orders, whatever your team looks up most. You are browsing and editing real production-shaped data immediately.

The first afternoon

Add the actions support actually needs, a refund, a plan change, an impersonation link, and a dashboard for the numbers ops watches. The admin starts replacing console sessions.

Day one

Put it behind your existing auth with policies per team, and ship it. Support and ops start doing their own lookups and changes in production instead of pinging an engineer.

By the end of the week

The team runs on it. The scattered half-built screens and the console-only workflows retire, and your internal tools are one maintained app instead of a second codebase you own forever.

Prefer to prompt?

Hand this to Claude Code, Cursor, or whatever agent you build with, and review what it ships like any other pull request.

Build a new Ruby on Rails application whose back office runs on Avo 4 (https://avohq.io, docs at https://docs.avohq.io/4.0/). There is no existing app or schema yet, so you are creating both the business data this company operates on and the internal tools the team uses to run it.

1. Generate the app with rails new using current defaults, then wire up sign-in with bin/rails generate authentication so there is a real User and session behind everything. Add the avo gem, bundle, run bin/rails generate avo:install, and mount Avo at /avo so it sits behind that authentication.
2. Design the domain before touching migrations. This is a company's back office, so reason from first principles about what such a business actually operates on: the customer accounts it serves, the people inside them, the orders or subscriptions that generate revenue, the payments and refunds against those orders, and the support conversations the team fields. Decide which lifecycle states belong on a record as an enum (an account that is trialing, active, or suspended) and which deserve their own table (a payment with its own history). Map the associations, then write the migrations once the shape holds together.
3. Give every model an Avo resource with bin/rails generate avo:resource. Match each field to the column you designed: a select over an enum, a badge over a status, a money field for revenue and refunds, date_time for timestamps, and belongs_to and has_many for the associations. Set self.title to something a person reads, self.includes for the associations you render so the lists stay fast, and self.search over what support actually types, a name, an email, an order number (https://docs.avohq.io/4.0/resources.html).
4. Turn the operational verbs into Avo Actions: issue a refund, extend a trial, suspend an account, close a ticket. Because the app is new, write the logic these actions need as model methods or small service objects, then have each action call one, ask for confirmation, and run as the signed-in admin so the change is attributable.
5. Add filters and scopes for the queues each team lives in, trialing accounts, past due invoices, open tickets, so anyone lands on the right list without SQL. Give ops a dashboard with the numbers they watch, signups this week, MRR, open ticket count, using metric and chartkick cards (https://docs.avohq.io/4.0/dashboards.html).
6. Authorize with Pundit policies per team so support, finance, and ops each see and change exactly their slice, and an admin sees everything (https://docs.avohq.io/4.0/authorization.html).
7. Seed realistic sample data: a spread of accounts across every status, users under them, orders and payments with a few refunds, and open and closed support tickets, so every screen, filter, and dashboard card has something to show.
8. Boot the app, open /avo, and confirm the workflow end to end: search an account by email, run Extend trial on it, and watch the change land without a console session.

04 · start today

Stand up internal tools this week

Avo is per app with unlimited users, so the whole team works from it without the bill scaling with headcount. When you hit an edge Avo doesn't cover, you drop to plain Rails instead of filing a feature request.

More things teams run from their Rails app

Frequently asked questions

Can I build internal tools with Ruby on Rails?
Yes, and you almost certainly already are, one urgent screen at a time. Internal tools are admin panels, dashboards, and back-office CRUD over your existing models. Avo gives you a framework for all of them in your Rails app, so the second app your team runs on is maintained the same way as your product.
What is the best internal tool builder for Rails?
The best fit for a Rails team is a tool that lives inside the Rails app rather than a hosted platform that connects to your database from outside. Avo runs on your infrastructure, reads your models directly, and drops to plain Rails when you outgrow a screen. That keeps your data in your app and avoids per-seat pricing.
Does Avo replace Retool for Rails teams?
For most internal tooling, yes. Retool builds tools in a separate platform that reaches into your data over the network. Avo builds the same admin, dashboards, and workflows inside your Rails app, so there is no third-party service between your team and your database and no config to keep in sync with your schema.
Can non-developers use the tools I build?
Yes. Avo produces clean screens with the right fields, validation, and one-click actions, so support, ops, and finance work in them without touching the console or writing SQL. Policies limit each person to what they should see and do, which is what makes it safe to hand the tools to the whole company.
How does pricing work for a whole team?
Avo 4 is priced per application with unlimited users, not per seat. You can add everyone who needs the internal tools, support, ops, finance, engineering, without the cost scaling by headcount, which matters because internal tools are exactly the thing the entire company ends up using.
Does building internal tools in Avo mean maintaining two apps?
The opposite. Without a framework, your product and your internal admin are two codebases you build and maintain separately. Avo makes the internal app almost built for you on the models you already have, so it rides your existing Rails upgrades and conventions and stays one app instead of two.