Cuando tu aplicación Laravel crece y comienza a manejar más usuarios, una de las primeras optimizaciones que debes considerar es distribuir la carga de tu base de datos. Laravel ofrece una funcionalidad nativa elegante para separar operaciones de lectura y escritura: las conexiones Read/Write.
En este artículo te explico cómo configurar y aprovechar esta funcionalidad para escalar tu aplicación de manera efectiva.
¿Por qué separar lecturas y escrituras?
En la mayoría de aplicaciones web, el 80% del tráfico son operaciones de lectura (SELECT) y solo el 20% son escrituras (INSERT, UPDATE, DELETE). Esta distribución desigual crea oportunidades de optimización:
Mejor rendimiento: Las lecturas pueden distribuirse entre múltiples servidores
Escalabilidad horizontal: Puedes agregar más servidores de lectura según crezcas
Menos contención: Las escrituras no compiten con lecturas por recursos
Configurando Read/Write en Laravel
Laravel hace increíblemente fácil implementar esta separación. Solo necesitas configurar tu conexión de base de datos con hosts específicos para lectura y escritura:
<?php
// config/database.php
'mysql' => [
'read' => [
'host' => [
'192.168.1.10', // Servidor de lectura principal
'192.168.1.11', // Servidor de lectura secundario
],
],
'write' => [
'host' => [
'192.168.1.5', // Servidor de escritura (Master)
],
],
'sticky' => true,
// Configuración compartida
'driver' => 'mysql',
'port' => '3306',
'database' => env('DB_DATABASE', 'laravel'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'strict' => true,
'engine' => null,
],Cómo funciona automáticamente
Una vez configurado, Laravel maneja toda la lógica automáticamente:
<?php
// Estas operaciones van automáticamente al servidor WRITE
User::create(['name' => 'Juan', 'email' => '[email protected]']);
Post::where('id', 1)->update(['title' => 'Nuevo título']);
Comment::destroy(5);
// Estas operaciones van automáticamente al servidor READ
$users = User::all();
$posts = Post::where('published', true)->get();
$comments = Comment::with('user')->paginate(15);No necesitas cambiar tu código existente. Laravel detecta automáticamente el tipo de operación y usa la conexión apropiada.
La opción Sticky: ¿Qué es y cuándo usarla?
La opción sticky es crucial para evitar problemas de consistencia:
<?php
'sticky' => true,Sin sticky (false):
<?php
// Usuario crea un post
$post = Post::create(['title' => 'Mi nuevo post']); // Va a WRITE
// Inmediatamente intenta verlo
$post = Post::find($post->id); // Va a READ (¡podría no estar sincronizado aún!)Con sticky (true):
<?php
// Usuario crea un post
$post = Post::create(['title' => 'Mi nuevo post']); // Va a WRITE
// Inmediatamente intenta verlo
$post = Post::find($post->id); // Sigue usando WRITE en esta requestRecomendación: Siempre usa sticky => true en producción.
Implementación en tu Service Layer
Para tener máximo control, puedes manejar las conexiones explícitamente en tu Service Layer:
<?php
class PostService
{
public function createPost(array $data): Post
{
// Escrituras explícitas al Master
return DB::connection('mysql')->transaction(function () use ($data) {
return Post::create($data);
});
}
public function getPublishedPosts(): Collection
{
// Lecturas pueden ir a cualquier READ server
return Post::where('published', true)
->latest()
->get();
}
public function getPostStats(): array
{
// Queries pesadas van a READ servers
return [
'total' => Post::count(),
'published' => Post::where('published', true)->count(),
'avg_comments' => Post::withCount('comments')->avg('comments_count'),
];
}
}Variables de entorno para diferentes entornos
Para manejar múltiples entornos fácilmente:
# .env.production
DB_READ_HOST_1=replica1.myapp.com
DB_READ_HOST_2=replica2.myapp.com
DB_WRITE_HOST=master.myapp.com
# .env.local
DB_READ_HOST_1=127.0.0.1
DB_WRITE_HOST=127.0.0.1<?php
'read' => [
'host' => array_filter([
env('DB_READ_HOST_1'),
env('DB_READ_HOST_2'),
env('DB_READ_HOST_3'),
]),
],
'write' => [
'host' => [env('DB_WRITE_HOST', '127.0.0.1')],
],Monitoreo y debugging
Para verificar que todo funciona correctamente, puedes usar eventos de Laravel:
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Events\QueryExecuted;
public function boot()
{
DB::listen(function (QueryExecuted $query) {
if (app()->environment('local')) {
$connection = $query->connection->getName();
Log::info("Query on {$connection}: {$query->sql}");
}
});
}El requisito previo: Replicación MySQL
Aquí está el detalle importante que muchos developers pasan por alto: para que las conexiones Read/Write funcionen correctamente, necesitas tener configurada previamente la replicación MySQL entre tus servidores.
Laravel maneja el enrutamiento de consultas, pero no configura la sincronización de datos. Necesitas:
Un servidor Master configurado para replicación
Uno o más servidores Replica sincronizados automáticamente
Usuarios de base de datos con permisos apropiados
Monitoreo de la sincronización
Si nunca has configurado replicación MySQL desde cero, puede parecer intimidante. Involucra configuración de archivos my.cnf, binary logs, usuarios de replicación, y comandos específicos de MySQL.
Para developers que quieren aprender este proceso completo, desde la configuración de MySQL Master-Replica hasta su integración con Laravel, he creado un curso práctico: Master-Replica MySQL con Laravel y Docker. En una hora cubrimos todo el setup usando Docker, verificaciones de funcionamiento, y mejores prácticas para producción.
Conclusión
Las conexiones Read/Write de Laravel son una herramienta poderosa para escalar aplicaciones, pero son solo una pieza del puzzle. Combinadas con una infraestructura de replicación MySQL bien configurada, pueden mejorar significativamente el rendimiento de tu aplicación.
Lo mejor de esta funcionalidad de Laravel es su transparencia: una vez configurada, tu código existente funcionará automáticamente con la nueva arquitectura, sin necesidad de refactoring masivo.
Recursos adicionales:
Curso Laravel 12
Completo 2026
El único curso 100% actualizado que incluye Laravel 12, Livewire 3, Vue 3, React 19 e Inertia 2. Aprende con proyectos reales y las últimas funcionalidades.
star Incluido en cualquier suscripción