Database sharding is the process of splitting a large table into multiple smaller databases (shards), where each shard holds a subset of your total data. This makes your application more scalable, performant, and fault-tolerant.
Our Rails app was receiving lakhs of orders in real time. Our orders table became a bottleneck:
We had to scale horizontally—without rewriting the whole app.
orders Table by user_idWe split the orders into 8 databases:
order_shard_0 to order_shard_7user_id % 8 to route trafficdatabase.yml Setupproduction:
primary:
database: app_primary
adapter: postgresql
order_shard_0:
database: app_orders_0
adapter: postgresql
# ...up to order_shard_7
class OrderBase < ApplicationRecord
self.abstract_class = true
end
class Order < OrderBase
belongs_to :user
end
module ShardRouter
SHARDS = %i[order_shard_0 order_shard_1 ... order_shard_7]
def self.for_user(user_id)
SHARDS[user_id % SHARDS.size]
end
end
class OrderService
def initialize(user_id)
@user_id = user_id
@shard = ShardRouter.for_user(user_id)
end
def create_order(params)
ActiveRecord::Base.connected_to(database: @shard) do
Order.create!(params.merge(user_id: @user_id))
end
end
def fetch_latest_orders(limit = 10)
ActiveRecord::Base.connected_to(database: @shard) do
Order.where(user_id: @user_id).order(created_at: :desc).limit(limit)
end
end
end
service = OrderService.new(current_user.id)
service.create_order(price: 100, quantity: 2, symbol: "RELIANCE")
orders = service.fetch_latest_orders
Yes, you can do order.user. But Rails does this in two queries:
SELECT * FROM orders ... -- shard
SELECT * FROM users ... -- primary DB
order.user ✅order.build_user ✅User.has_many :orders ❌Order.includes(:user) ❌user_id (or other sharding key) consistently| Metric | Before | After |
|---|---|---|
| Order fetch (10 rows) | ~500ms | ~80ms |
| Write throughput | Saturated | Smooth |
| Lock contention | High | Low |
Sharding helped us break through scaling walls. It takes effort—but if you're hitting database limits, this might be your solution too.
orders by user_id % 8connected_to in service layerQuestions or thoughts? Email me