Does Ruby on Rails Work With Drizzle ORM?
You can use Drizzle ORM with Rails, but it requires running a separate Node.js process since Drizzle is TypeScript-only and Rails is Ruby-native.
Quick Facts
How Ruby on Rails Works With Drizzle ORM
Ruby on Rails and Drizzle ORM are fundamentally misaligned by language—Rails is a Ruby framework with ActiveRecord as its native ORM, while Drizzle is a TypeScript library. Direct integration is impossible. However, you can architect a solution where Rails serves as your backend API while a separate Node.js/TypeScript service uses Drizzle for database access. This works best in a microservices or API-gateway pattern where Rails handles business logic and Drizzle handles data persistence.
The practical approach involves running two separate processes: a Rails API server (potentially just for endpoints) and a Node.js service with Drizzle for database operations. You'd communicate between them via HTTP/GraphQL or message queues. This adds operational complexity—you're now managing two runtimes, deployments, and potential synchronization issues. The developer experience becomes split across languages, making it harder to maintain cohesive application logic.
A more realistic scenario: use this only if you have specific reasons (existing Rails infrastructure, TypeScript requirements elsewhere, or Drizzle's SQL-generation superiority for complex queries). For new projects, commit to one ecosystem entirely.
Best Use Cases
Rails API calling a Drizzle-powered Node.js service
npm install drizzle-orm drizzle-kit postgres && gem install rails# config/initializers/drizzle_client.rb
require 'net/http'
class DrizzleClient
BASE_URL = ENV['DRIZZLE_SERVICE_URL'] || 'http://localhost:3001'
def self.get_user(user_id)
uri = URI("#{BASE_URL}/api/users/#{user_id}")
response = Net::HTTP.get_response(uri)
JSON.parse(response.body) if response.is_a?(Net::HTTPSuccess)
end
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
def show
user = DrizzleClient.get_user(params[:id])
render json: user
end
end
# Node.js/Express service (separate process)
// src/routes/users.ts
import { db } from './db'
import { users } from './schema'
import { eq } from 'drizzle-orm'
app.get('/api/users/:id', async (req, res) => {
const user = await db.select().from(users).where(eq(users.id, req.params.id))
res.json(user[0])
})Known Issues & Gotchas
No shared database migrations between Rails and Drizzle
Fix: Maintain migrations in only one system (preferably Drizzle's migration runner) and keep both systems in sync manually or via shared migration files
Rails ActiveRecord and Drizzle will compete for the same database, causing schema conflicts
Fix: If both access the same DB, isolate table ownership—have Drizzle manage specific tables only, not the entire schema
No Rails convention support—you lose Rails' automatic timestamp columns, validations, and associations
Fix: Implement your own validation/timestamp logic in the TypeScript layer or use database triggers
Debugging and error tracking across two runtimes becomes significantly harder
Fix: Use centralized logging (DataDog, Sentry) and enforce strict error boundary patterns between services
Alternatives
- •Rails + ActiveRecord (native, zero friction, Ruby-native ORM with excellent Rails integration)
- •Rails + Sequel (Ruby ORM with more flexibility than ActiveRecord, better for complex queries)
- •Node.js Express + Drizzle ORM (pure TypeScript stack, purpose-built for this combination)
Resources
Related Compatibility Guides
Explore more compatibility guides