Skip to content

Ruby and Rails development

Three situations bring people to a Ruby page. An application that has drifted several versions behind support. One whose original team has moved on. One where somebody has proposed replacing the whole thing. None of the three needs a rewrite to fix, whatever the last supplier told you.

01Capabilities

Four ways a mature product keeps shipping

Ruby in practice means Ruby on Rails, and Rails is very good at one thing: getting a conventional product built and changed quickly. Almost all the work below is about keeping that property once the product is a few years old and the people who started it have gone somewhere else.

  • Handover

    Taking over something nobody currently owns

    The original team has gone, the written notes describe an intention from four years ago, and the release process lives in one person's command history. Mapping what actually runs comes before any promise about what changes next, and that ongoing ownership is what our maintenance and support work covers.

  • Versions

    Getting back onto a supported version

    Applications on a retired language version and an unsupported framework, where the blocker is nearly always a handful of abandoned add-ons rather than the framework itself. Security patching is the argument for this that actually gets budget, and it is legacy modernization in the ordinary sense.

  • Features

    Still shipping inside a decade of conventions

    Continuing to release in a codebase carrying ten years of decisions, including the ones that turned out to be mistakes. Hospitality and e-commerce products of that vintage are common, and the skill is changing them without a weekend of firefighting afterwards.

  • Extraction

    Pulling one piece out, where it is justified

    Separating a single part when it genuinely needs to grow or change on its own schedule. Always behind a stable interface and never as one large split, because a split you cannot reverse is a bet rather than an architecture. We do this under an ISO 27001:2022 certified information-security management system.

02Fit

Keep it, extract from it, or start moving off it

Rails still ships conventional products faster than most of what people replace it with, and that matters, because the pressure to migrate away is usually organisational rather than technical. Below is where we would keep it, where another language suits a new component, and where the migration you were planning costs more than it returns. Each row names the move that fits, whether that is Rails, one component in another language, or keeping a stable system as it is.

Six situations, and what we would tell you in each
Your situationWhat we recommend
An existing application, a sound model of the business, and change that has become slow and frightening Upgrade in placeFix how the data is fetched at the same time. A rewrite is the expensive way to buy what maintenance already delivers.
A new conventional product, a small team, and time to first customers is the real constraint Either is fineRails is a reasonable call and so is Django. Choose on the language your team will still be maintaining in three years.
A high-volume service with a response-time figure written into the contract Go or Rust for itThat is not what this runtime is good at. Build that one component in Go (Golang) or Rust and leave the rest alone.
You want off Rails because hiring Ruby developers has become hard Replace what changesThat is a hiring problem, and a rewrite is a very expensive solution to one. Replace the parts that actually change and leave the stable remainder.
Your organisation standardises on .NET or Java and this is the lone outlier Migrate slowlyA legitimate reason. Move into C# or Java piece by piece rather than freezing features for a year.
The application is stable, patched, and simply not fashionable Keep the applicationSpend the budget where change is genuinely blocked. An application nobody is fighting is not a problem waiting to be funded.

Scope

What we own here is the upgrade path and everything that follows from it. Which add-ons get replaced, and why. How much of the behaviour has to be covered by tests before we touch the risky parts. And whether your own team can keep releasing once we step back. We run that work under an ISO 27001:2022 certified information-security management system, alongside ISO 9001:2015. unicrew has been building software since 2012, with 100+ senior in-house engineers across six countries. The rows above that keep the work deliberately small are there because, on a mature application, that is often what the problem needs.

On a Ruby application, we read the dependency tree before the code. It shows which of the gems that made year one fast are still maintained. That tells you what the next two years will cost.

Yaroslav HavrylivSenior Engineering Manager, unicrew

03Delivery

Taking custody of an application whose authors have left

Four steps in this order. On something you did not write, the first two are where the surprises live and where a bad estimate normally gets made.

  1. Establish what actually runsLanguage version, the pinned dependency list, the background job system, the scheduled tasks, the release path and the settings nobody wrote down. On applications of this age the release process is usually the least documented and most fragile part of the whole system.
  2. Get the paths that earn money under testTests driven through the screens, where the internals resist being tested directly. These codebases often have plenty of tests and thin coverage of the flows that actually bring in revenue, which is a different problem from having no tests at all.
  3. Upgrade in ordered stepsLanguage first or framework first depending on what the dependency list allows, one version at a time, with warnings about retired behaviour treated as work rather than noise. Make two jumps at once and you lose the ability to attribute a failure to a cause.
  4. Fix the slow parts where they liveLoops that query the database once per row, missing indexes, jobs retrying forever, and hooks doing things nobody expects. Complaints about speed here are usually a data-access problem in a framework costume, and moving to a bigger server does not fix them.

04Stack

What runs beside the application in production

The decisions that usually arrive with a product of this age, each with its own page if that is the one you are actually taking.

05Questions

Asked by owners deciding whether to reinvest

Answered the way we would answer them live. If yours is not here, it is a good first message.

Yes, and on a mature codebase it often works well, because your people hold the history and ours hold the upgrade experience. The upgrade plan has an owner from the first ticket: an architect outside the delivery team reviews it, and the work goes through the same QA practice as our own projects. Team extension is managed teams; an outcome is custom software development.

Usually not, and certainly not as one project. The reasons that hold up are an organisation-wide standard on another stack, or a business that has genuinely outgrown the conventions. The reason that does not hold up alone is that it feels dated, because the rewrite costs more than several years of maintenance and reintroduces bugs you already paid to find. Where migration is right, we move pieces out behind a stable interface.

Yes, and the right shape is version by version rather than a jump to the current release. Expect the abandoned add-ons to be the real cost: each is a decision about replacing, forking or dropping a capability, and those decisions need you in the room. An unsupported language version is a live security exposure rather than only a debt item, which is normally what gets the work funded.

They are close enough that the language and the people decide it. Django if your team leans Python, or the product will grow data and machine-learning work you want next door rather than over an interface. Rails if your team leans Ruby and the product is conventional, with a lot of screens, where the conventions and the code generators genuinely save weeks. Anyone claiming one is simply better has not asked who maintains it.

That is the normal starting position and it is fixable without rewriting the suite. We map the flows that bring in revenue, then cover those end to end through the screens, in preference to adding more small tests around individual classes. A suite that is slow and green tells you nothing; a smaller set covering checkout, billing and sign-in tells you whether today's release is safe.

A scoping call with an engineer. For an existing application we ask for read access to the repository first, because the dependency list and the test suite tell us more in twenty minutes than a long conversation does. What comes back is written: what we would upgrade, in what order, what we would extract, and what we would keep exactly as it is. Most engagements start within two to four weeks.

Three shapes, and which fits depends on how settled the scope is. Time and materials is billed hourly and quoted per project, which suits work still moving. Fixed price is outcome based and quoted per project, and we only offer it after the first read, because a fixed number on a system nobody has opened is a guess. Team extension is billed monthly per engineer, and the rate depends on the seniority mix, so it is quoted rather than listed.

Inherited a product nobody wants to be responsible for?

Tell us what it does, which versions it is stuck on, and what breaks. You will get an engineer's read on whether it needs upgrading, pulling apart, or keeping as it is.

Book a scoping call

Thank you

Thanks for your message. We will get in touch with you shortly.