Build on Rails

Build an ERP on Rails

You do not need SAP. You need the 20% of an ERP your business actually runs on, products, orders, purchasing, inventory, invoices, unified over the Postgres data you already have.

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

01

01 · the hand-built version

What building an ERP by hand actually costs

Building an ERP usually means one of two mistakes: buying a monolith suite that fits no one, or trying to rebuild SAP in-house. There is a saner third option.

  • 01

    A boxed suite fits no one well

    A boxed ERP forces your business into its data model, and the first year is spent configuring the defaults back out. You end up shaping the company around the tool instead of the tool around the company.

  • 02

    Rebuilding SAP is a career, not a project

    Nobody actually ships a full ERP. What you ship is an ever-growing pile of admin screens over your own tables, with no end state, quietly becoming the thing you have to maintain forever.

  • 03

    Your data is in Postgres, just not together

    Products, orders, inventory, and invoices already exist as Active Record models. What is missing is a single place to run them from, so today it lives across a dozen screens, a few rake tasks, and a spreadsheet.

  • 04

    Every module is another app to own

    Purchasing here, inventory there, invoicing somewhere else, each a bespoke screen with its own auth and its own quirks. The maintenance is not one system, it is a handful of small ones that never quite match.

02

02 · the Avo version

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

Avo takes the honest path. Instead of a suite, it turns the models you already have, Product, Order, PurchaseOrder, StockItem, Invoice, Customer, into one connected set of screens. Related records link to each other so you navigate the business rather than raw tables, operations run as actions that call your own logic, and the whole thing lives in your Rails app over your existing Postgres. You build the fifth of an ERP your team actually uses and skip the rest.

Your domain, not a vendor's

Resources map one to one to your models, so the ERP speaks products, orders, and invoices in your company's terms instead of forcing your operation into someone else's schema.

Modules that link up

belongs_to and has_many fields connect an order to its line items, a purchase order to its supplier, an invoice to its customer, so a person clicks through the business instead of joining tables in their head.

Operations as real actions

Receive stock, approve a purchase order, mark an invoice paid: each is an Avo Action calling the service object you already trust, behind a confirmation and your Pundit policy, not a raw edit to a row.

Reorder points and past-due invoices, surfaced

A scope for stock below its reorder point, a filter for invoices past due, a saved view of purchase orders awaiting approval: the morning check becomes opening three lists, not running three reports.

Dashboards over live data

Build dashboards for stock levels, receivables, and order volume on the same Postgres your app writes to, with no export and no separate warehouse to keep in sync.

One app, and your data stays in it

It runs inside Rails, so your operational data never leaves your database, and when you reach the edge of what is provided you drop to plain Rails.

One invoice resource, linked to its customer and line items, with a mark-paid action and an unpaid scope:

class Avo::Resources::Invoice < Avo::BaseResource
  self.title = :number
  self.includes = [:customer, :line_items]
  self.default_sort_column = :issued_on

  def fields
    field :id, as: :id
    field :number, as: :text, readonly: true
    field :status, as: :badge, options: {
      warning: %w[draft sent],
      success: %w[paid],
      danger: %w[overdue void]
    }
    field :total, as: :number
    field :issued_on, as: :date, sortable: true
    field :due_on, as: :date
    field :customer, as: :belongs_to
    field :line_items, as: :has_many
  end

  def actions
    action Avo::Actions::MarkInvoicePaid
  end

  def scopes
    scope Avo::Scopes::Unpaid
  end
end
03

03 · the timeline

From first resource to the team running on it

Hour one

Generate resources for the models your business already runs on, Product, Order, Invoice, Customer, and click through them connected: an order to its customer to their invoices, all live over your Postgres.

Day one

Add the operations, receive stock, approve a purchase order, mark an invoice paid, as Avo Actions behind your Pundit policies, and put it in production against your real data.

End of the week

The spreadsheet-and-console workflow for the parts of an ERP you actually use is a single Rails app, and you never had to buy a suite or start rebuilding SAP.

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.

Stand up a fresh Ruby on Rails application that runs the useful fifth of an ERP, with Avo 4 as the operations UI (https://avohq.io, docs at https://docs.avohq.io/4.0/). There is no existing app or schema yet, so scaffold the whole thing, and resist the urge to rebuild a full suite: build only the screens the business actually runs on.

1. Run rails new for a new app with Postgres as the database and the usual defaults. Set up sign-in with the built-in Rails authentication generator (bin/rails generate authentication). Add the avo gem, bundle, run bin/rails generate avo:install, and mount Avo at /avo so it sits behind the authentication you just generated.
2. Work out the data model from the ground up before touching a migration. Reason about what this operation genuinely needs: the core entities, the lifecycle each one moves through (a status enum where a column is enough, its own table where a state carries data of its own), and how they relate to each other. Products, orders and their line items, purchasing, stock, invoices, and the customers behind them are the kind of concepts an ERP has to cover, so use them to pressure-test your design rather than as a fixed list to transcribe. Sketch the entities and associations, then write the migrations and models.
3. Generate an Avo resource for each model with bin/rails generate avo:resource, and wire them together with belongs_to and has_many fields so a person clicks from an order to its customer and line items instead of joining tables in their head. Give each resource a readable self.title, self.search over the columns people look things up by, self.includes for the associations you render, and field types matched to the columns you created: a badge over a status column with sensible option colors, number and money fields for amounts, dates for anything scheduled.
4. Turn the operations into Avo Actions behind confirmations, the verbs the business runs on, such as receiving stock, approving a purchase order, or marking an invoice paid. Since the app is new, put the real logic in model methods or small service objects and have each action call into those rather than mutating rows inline.
5. Add the morning-check lists as scopes and filters driven by your own columns, such as stock below its reorder point, invoices past due, and purchase orders awaiting approval, then build a dashboard over the same Postgres the app writes to for the numbers the team watches: stock levels, receivables, order volume (https://docs.avohq.io/4.0/dashboards.html).
6. Gate everything with Pundit authorization so each role sees only what it should, warehouse staff on stock and receiving, finance on invoices and receivables, and so on (https://docs.avohq.io/4.0/authorization.html).
7. Seed realistic sample data across every model, products in stock and low, orders in various states, purchase orders awaiting approval, and invoices spanning draft, sent, paid, and overdue, so every list, scope, and dashboard has something to show.
8. Boot the app, open /avo, click from an order through to its customer and their invoices, and run one operation end to end by marking a seeded overdue invoice paid.

04 · start today

Stand up an ERP 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 an ERP with Ruby on Rails?
Yes, as long as you scope it honestly. Trying to rebuild a full ERP suite in Rails is a trap, but the part most businesses actually use, products, orders, purchasing, inventory, and invoices over their own data, maps cleanly onto Active Record models. Avo turns those models into a connected set of operational screens without a monolith.
Should I build a full ERP or use a suite?
Most teams use only a fraction of what a suite offers, and forcing the business into a boxed ERP's data model costs more than it saves. The pragmatic path is to build the modules you genuinely run on, over the Postgres data you already have, and skip the 80% no one on your team will open. That is the case for building it in Rails with Avo rather than buying SAP.
Is there an open source ERP for Rails?
The avo gem itself is open source, and there are open-source Rails ERPs you can fork. The catch with a ready-made ERP is that it brings its own schema and assumptions. Avo takes the opposite approach: it builds the ERP screens over the models and database you already have, so you keep your own data model.
How do I unify products, orders, and invoices in one Rails admin?
Generate an Avo resource for each model and connect them with belongs_to and has_many fields. An order links to its customer and line items, an invoice links back to that customer, so the whole operation is navigable from one app. Because it is all in your Rails codebase, the relationships are your existing Active Record associations, not a new data layer.
Does my ERP data stay in my own database?
Yes. Avo runs inside your Rails application, so products, orders, inventory, and invoices stay in your Postgres and never travel to a third-party service. There is no vendor sitting between your team and your operational data, which is often the whole reason a company hesitates to put its ERP in a hosted tool.
How much does a Rails ERP cost with Avo?
Avo is priced per application with unlimited users, so every person who runs operations, purchasing, warehouse staff, finance, sales, is included at the same price. An ERP touches most of the company, which is exactly where per-seat pricing hurts most.