The Hidden Problem Behind Massive Validations
When we validate arrays of data in Laravel using rules like unique, the framework executes one query per element in the array.
For example, if you validate a list of emails using the rule unique:users,email, Laravel will run a query for each email.
This results in what’s known as the N+1 problem, a classic performance bottleneck in database operations.
What Is the N+1 Problem in Validations?
Here’s what happens:
- You have an array with N elements.
- Laravel executes N SQL queries to validate each one.
- As the array grows, the number of queries grows too.
This might not be noticeable for small datasets, but in massive operations (imports, APIs, data migrations), it quickly becomes a serious performance issue.
The Solution
Batch Validations with laravel-batch-validation
dazza-dev/laravel-batch-validation solves this problem by optimizing how Laravel handles database-dependent validation rules.
Instead of validating each element individually, this package groups validations and performs a single WHERE IN query per batch.
This means:
- Hundreds of queries become just one or a few.
- You keep Laravel’s native validation syntax.
- You gain massive performance improvements with zero code complexity.
Installation
composer require dazza-dev/laravel-batch-validation
Laravel will automatically detect the package thanks to auto-discovery,
so you don’t need to register anything manually.
Practical Example: Validating Arrays Without N+1
Imagine you receive an array of contacts to validate:
use Illuminate\Support\Facades\Validator;
$data = [
['name' => 'User 1', 'email' => 'user1@example.com'],
['name' => 'User 2', 'email' => 'user2@example.com'],
['name' => 'User 3', 'email' => 'user3@example.com'],
];
// Create the Validator instance
$validator = Validator::make($data, [
'*.name' => 'required',
'*.email' => 'email:strict|unique:contacts,email',
]);
// Validate in batches (this prevents the N+1 problem)
$validator->validateInBatches();
// Validation fails
if ($validator->fails()) {
throw new \Exception(json_encode($validator->errors()->messages()));
}
With this approach, instead of executing one query per email,
the package groups all values and runs a single WHERE IN query.
Control the Batch Size
In some cases, you may want to adjust the batch size to balance performance and memory usage.
You can do this by passing the batchSize parameter to validateInBatches:
$validator->validateInBatches(batchSize: 20);
This means the validator will process the data in groups of 20 records at a time perfect for handling very large datasets efficiently.
Integration with FormRequests
The package also integrates seamlessly with Laravel’s FormRequest classes, keeping your validation flow clean and native.
For example:
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Validator;
class StoreContactRequest extends FormRequest
{
public function rules(): array
{
return [
'*.name' => 'required',
'*.email' => 'email:strict|unique:contacts,email',
];
}
public function withValidator(Validator $validator)
{
if (method_exists($validator, 'validateInBatches')) {
$validator->validateInBatches(batchSize: 100);
}
}
}
This ensures that even your FormRequest validations are executed in batches, without changing any of your existing rules.
Result
Conclusion
dazza-dev/laravel-batch-validation is a smart and transparent optimization for Laravel projects that need to validate large datasets.
Fewer queries. Faster validations. Same Laravel syntax.
A must-have tool for imports, massive APIs, and large-scale data validations.


Top comments (0)