2013
We start 10KB with Ruby
Ewout and Roland found 10KB. After working in PHP, they choose the mature Rails approach and the pleasure of elegant, readable Ruby code.
Few languages let you express an idea as elegantly and clearly as Ruby. We have used it since founding 10KB in 2013 and still do a lot of ongoing development in it. Around half our projects now use TypeScript, but our love of Ruby has never gone away. And when the Ruby on Rails approach fits your project, you can build something good remarkably quickly.
Part of our work since 2013
Elegant code that reads close to everyday language
Fast development with Rails conventions

Ruby at 10KB
When Ewout and Roland founded 10KB together in 2013, most of their development experience was in PHP. Rails felt like a more mature framework, and Ruby's standard library was more extensive and pleasant to use. But perhaps the biggest attraction was how beautifully you could write code in it.
That enjoyment has stayed with us. 5.times reads as “five times”. With Rails, 3.days.ago is simply “three days ago”. There is less technical notation between you and the intent. That might sound like a concern for developers, but when software keeps evolving for years, understandable code matters to the client too.

Why we use Ruby and Rails
Ruby lets you write code that almost reads like a sentence. Going through a list, adding amounts or naming a condition often takes very little extra notation. We find that one of the language's best qualities. Your attention goes to what the code does, which also helps the colleague who works on it next.
We can extend Ruby with terms that belong to an application. A reminder plan might literally say: email after three days, call after seven. A small domain-specific language, or DSL, makes recurring rules easy to read and change. Further down, we show how little code this takes.
Rails has an established approach to forms, database access, email and background jobs. The framework determines how those parts work together. When that suits your application, we can spend less time on setup and get to work on the features you need.
Ruby lets you write code that almost reads like a sentence. Going through a list, adding amounts or naming a condition often takes very little extra notation. We find that one of the language's best qualities. Your attention goes to what the code does, which also helps the colleague who works on it next.
How we decide
Rails is opinionated: it has firm ideas about how to build a web application. Those conventions are a real advantage when your project fits. A portal with accounts, forms, overview screens and recurring workflows can take shape quickly.
If we need to depart from that approach in many places, the benefit diminishes. We spend more time on exceptions, and another language or framework may fit better. We therefore look at the interactions you need, existing systems and the team that will maintain the application.
Static type checking matters too: feedback about data types before code runs. Ruby has tools for this, but in our work we find them less developed than TypeScript's. That is one consideration alongside development speed, readability and project fit. The fact that around 50% of our projects now use TypeScript does nothing to diminish the pleasure we take in writing Ruby.
Discuss which approach fits your project
In our work
For LiVvE, we built a Rails application for homeowners' association management, with accounting, document processing and a portal for managers and members. Recurring contributions and reminders are handled in the same environment.
At SGI Compliance, we develop Werkplanner with configurable forms and project documents. At Smartfile, we improved authorisation, tests and deployments for existing Rails software. Ruby is part of our work both when building business applications and when developing them further.
See LiVvE in practice
The structure behind Rails
Rails helped popularise MVC among web frameworks. The pattern already existed, but Rails made it a recognisable starting point: data and business rules, presentation and request handling each have a place.
Take a customer opening an invoice. The Controller receives the request and asks for the right invoice. The Model holds the data and rules, such as how the total is calculated. The View turns that into the screen the customer sees.
A change to the invoice's appearance therefore need not change its calculation. And an updated calculation need not be rewritten for every screen. That shared structure helps us find where a change belongs.
Try reading it aloud
You could create a counter, increment it and check whether you are done. Ruby also lets you simply write 5.times. The block that follows says what should happen five times. And sum adds a list of amounts.
That is Ruby's appeal in a few lines: the code shows the intent. Here we create five invoice names and add amounts in whole euros.
# Ruby almost reads like a sentence
invoices = []
5.times do |number|
invoices << "Invoice #{number + 1}"
end
puts invoices
# Invoice 1, Invoice 2, ... Invoice 5
# Each name appears on its own line.
amounts = [20, 35, 45]
puts amounts.sum
# 100 euros, without maintaining a counter yourself.Rails builds on that idea
Active Support, part of Rails, adds words such as days and ago. You can write “three days ago” without calculating seconds yourself. 2.weeks.from_now does the same for a point in the future.
Here we use it to check whether an invoice is more than three days old. 5.times is part of Ruby itself; the time expressions come from Active Support. You can also use that library outside a full Rails application.
# Time in everyday words
require "active_support/all"
# Active Support adds these time expressions.
cutoff = 3.days.ago
issued_at = 5.days.ago
if issued_at < cutoff
puts "This invoice is over three days old."
end
# A point in the future reads naturally too.
next_review = 2.weeks.from_now
puts next_review.to_date
# The date two weeks from now.
# No bare numbers with units you have to guess.
# 3.days is a duration; 3.days.ago is a point in time.The words of your application
We can take that readability further ourselves. A DSL is a small language for a particular subject. Here we make after 3.days, via: :email a valid rule in a reminder plan. It is still ordinary Ruby code; we supply the words and their meaning.
The class defines what after does. Below it, the plan reads almost like a work instruction. Changing a delay then takes a change in one clear place. This example only describes the steps; it does not schedule jobs or send messages.
# Our own language for reminders
class ReminderPlan
attr_reader :steps
def initialize(&rules)
@steps = []
instance_eval(&rules)
end
def after(delay, via:)
@steps << { delay: delay, via: via }
end
end
# This is our own DSL, written in ordinary Ruby.
plan = ReminderPlan.new do
after 3.days, via: :email
after 7.days, via: :phone
end
# Inspect the rules we have recorded.
plan.steps.each do |step|
days = step[:delay].in_days.to_i
puts "After #{days} days: #{step[:via]}"
end
# After 3 days: email
# After 7 days: phone
# The delays are relative to the start of the plan.
# Sending messages and scheduling jobs belong elsewhere.# Ruby almost reads like a sentence
invoices = []
5.times do |number|
invoices << "Invoice #{number + 1}"
end
puts invoices
# Invoice 1, Invoice 2, ... Invoice 5
# Each name appears on its own line.
amounts = [20, 35, 45]
puts amounts.sum
# 100 euros, without maintaining a counter yourself.
# Time in everyday words
require "active_support/all"
# Active Support adds these time expressions.
cutoff = 3.days.ago
issued_at = 5.days.ago
if issued_at < cutoff
puts "This invoice is over three days old."
end
# A point in the future reads naturally too.
next_review = 2.weeks.from_now
puts next_review.to_date
# The date two weeks from now.
# No bare numbers with units you have to guess.
# 3.days is a duration; 3.days.ago is a point in time.
# Our own language for reminders
class ReminderPlan
attr_reader :steps
def initialize(&rules)
@steps = []
instance_eval(&rules)
end
def after(delay, via:)
@steps << { delay: delay, via: via }
end
end
# This is our own DSL, written in ordinary Ruby.
plan = ReminderPlan.new do
after 3.days, via: :email
after 7.days, via: :phone
end
# Inspect the rules we have recorded.
plan.steps.each do |step|
days = step[:delay].in_days.to_i
puts "After #{days} days: #{step[:via]}"
end
# After 3 days: email
# After 7 days: phone
# The delays are relative to the start of the plan.
# Sending messages and scheduling jobs belong elsewhere.Ruby and Rails keep evolving
We have worked with Ruby since 2013. In that time, the language, development tools and ways of deploying Rails applications have changed considerably.
2013
Ewout and Roland found 10KB. After working in PHP, they choose the mature Rails approach and the pleasure of elegant, readable Ruby code.
2020
Ruby 3 introduces RBS for describing types and TypeProf for analysing code. Ruby stays dynamic but gains more tools for understanding data types before execution.
2021
Hotwire lets interactive screens be built largely from HTML on the server. A separate frontend application is no longer necessary for every interactive page.
2023
YJIT compiles frequently used Ruby code into machine code while the application runs. Ruby 3.3 improves the compiler's performance and memory use. The benefit to an application depends on its workload.
2024
Rails 8 includes Kamal 2 for deployments and Solid Queue for background jobs by default. The established Rails approach extends further from writing code to running the application.
Ruby and Rails at other companies
Shopify started in 2004 with two developers and an early Rails release. Its predecessor, snowboard shop Snowdevil, was built in under four months according to the Rails announcement at the time. Founder Tobias Lütke attributed that productivity in part to Rails.
That is the attraction when the fit is right: a small team can quickly build a working product and develop it further. At Shopify, that became a platform on which other entrepreneurs could start their shops.

Ruby and Rails at other companies
GitHub began in October 2007 as an evening and weekend project. Co-founder Tom Preston-Werner described how Chris Wanstrath built the Rails application while he worked on the Git integration and interface. Three months later, the private beta opened.
That division of work illustrates how Rails can help at the start: an existing foundation for the web app, with room for the team's own product idea. They could offer something useful early and develop it further with users.



Three projects where we worked with Ruby on Rails, from a business portal to existing practice software and an international sales platform.
Ewout

Want to build a first version quickly or develop an existing Rails application further? Talk to Ewout. We can look at your workflows, your team and how well the Rails approach fits.
CONTACT
Have a question or want to discuss your software? Leave your details and we will get back to you soon.