Fastest way to insert data in Laravel

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company

The Fastest Way to Insert Data in Laravel: Optimizing Bulk Operations

As a senior developer working with Laravel and relational databases, one of the most common performance bottlenecks we encounter is bulk data insertion. Migrating or copying large sets of related records often involves iterative operations that, while logically correct, result in significant database overhead. Your experience—seeing slow performance when inserting permissions for multiple users—is completely valid. The solution lies not just in writing more code, but in rethinking how you interact with the database.

This post will analyze why your current method is slow and provide concrete, high-performance strategies to drastically accelerate data insertion in Laravel.


Understanding the Bottleneck: Why Iteration is Slow

Your current approach involves iterating through a set of permissions and executing an individual create() operation inside the loop for each user:

foreach($permissions as $permission) {
    $permission->create([ /* ... data ... */ ]); // This executes one query per iteration
}

When you run this process across many users, you are forcing the database to perform numerous separate transaction commits and index lookups. For every single permission record, the database has to process overhead associated with initiating a new statement. This is inefficient for bulk operations, especially when dealing with hundreds or thousands of records.

This pattern is often referred to as an N+1 problem in the context of ORMs interacting with the database, where one request leads to many subsequent requests. We need to move away from row-by-row processing and embrace bulk insertion.

The Solution: Embracing Database Batching

The fastest way to insert data into a database from PHP is to minimize the number of round trips between your application and the database. Instead of executing $N$ separate INSERT statements, we want to execute one large statement that contains all the necessary data. This is achieved through Eloquent's mass insertion methods or raw SQL batching.

Method 1: Using Eloquent Mass Insertion (The Laravel Way)

For inserting multiple related records simultaneously, using Eloquent’s insert() method is dramatically faster than looping and calling save() or create(). This operation bundles all the data into a single INSERT query.

To utilize this effectively, you must first structure your data into a flat array of data points.

Here is how we can refactor your permission copying logic for optimal speed:

/**
 * Optimized Copy Branch User Permissions using Batch Insertion
 *
 * @param int $branchIdFrom
 * @param int $branchIdTo
 * @param int $userId
 * @return array
 */
public function copyBranchUserPermissionsOptimized($branchIdFrom, $branchIdTo, $userId)
{
    // 1. Retrieve the necessary permission IDs from the source branch
    $permissions = BranchPermissionUser::where('branch_id', $branchIdFrom)
        ->where('user_id', $userId)
        ->pluck('permission_id'); // Get only the IDs we need

    if ($permissions->isEmpty()) {
        return [];
    }

    // 2. Prepare the data for bulk insertion
    $dataToInsert = [];
    foreach ($permissions as $permissionId) {
        $dataToInsert[] = [
            'branch_id' => $branchIdTo,
            'permission_id' => $permissionId,
            'user_id' => $userId,
        ];
    }

    // 3. Execute a single bulk insert operation
    DB::table('branch_permission_users')->insert($dataToInsert); // Assuming 'branch_permission_users' is your target table

    return $permissions->toArray();
}

Why this is faster: Instead of executing potentially hundreds of individual SQL queries within the loop, the DB::table()->insert() method executes a single, optimized statement. This drastically reduces network latency and database query parsing overhead. For complex data migrations or heavy operations like those often seen in large applications, understanding these bulk operations is crucial for maintaining performance, aligning with best practices found on resources like laravelcompany.com.

Advanced Optimization: Raw SQL for Extreme Speed

If you are dealing with truly massive datasets (tens of thousands of records), the absolute fastest method involves bypassing Eloquent's abstraction layer and using raw SQL expressions, specifically DB::table()->insert() or even multi-row INSERT INTO ... SELECT statements. This eliminates all ORM overhead, though it requires careful management of escaping and data types.

For performance-critical operations that involve large-scale data manipulation, leveraging the underlying database engine directly—as Laravel allows via the DB facade—is often the ultimate optimization strategy.

Conclusion

The lesson here is that performance in application development is often found at the intersection of code logic and database interaction. Never default to row-by-row operations when dealing with bulk data manipulation in Laravel. By refactoring your permission copying method to utilize batch insertion, you transform an inefficient $N$-query process into a highly efficient single operation. This optimization will ensure that your application remains fast, scalable, and robust, whether you are managing simple updates or complex data migrations.