skip to content

In a fresh Laravel 13 app, which database connection is used by default, where is that decided, and how do you run a query on another named connection?

level: juniorimportance: must knowfreq 52%

answer

  1. config/database.php 'default' key
  2. DB_CONNECTION=sqlite in .env.example
  3. database/database.sqlite file
  4. DB::connection('pgsql')->table()
  5. connections array keyed by name

basics

~10 s

SQLite: config/database.php sets 'default' => env('DB_CONNECTION', 'sqlite') and the skeleton's .env.example sets DB_CONNECTION=sqlite, pointing at database/database.sqlite. DB::connection('pgsql') returns any other connection named in the 'connections' array.

solid answer

~30 s

In Laravel 13 the skeleton's `config/database.php` sets `'default' => env('DB_CONNECTION', 'sqlite')`, and `.env.example` ships `DB_CONNECTION=sqlite` with the MySQL lines commented out; the `sqlite` connection reads `DB_DATABASE`, falling back to `database/database.sqlite`. Every other connection lives in the `connections` array under a name (`sqlite`, `mysql`, `mariadb`, `pgsql`, `sqlsrv`, plus any you add). `DB::table()` and Eloquent use the default; `DB::connection('reporting')` returns the named connection, on which you call `table()`, `select()` or `transaction()`. An Eloquent model can pin its own connection with the `#[Connection('reporting')]` attribute or a `$connection` property. A single `DB_URL` can replace the separate host, port and credential variables.

code

php · 14 lines
php
<?php

use Illuminate\Support\Facades\DB;

// Default connection (SQLite in a fresh Laravel 13 app)
$members = DB::table('members')->count();

// A named connection from config/database.php 'connections'
$legacy = DB::connection('legacy')
    ->table('members')
    ->where('active', 1)
    ->count();

$name = DB::connection()->getName(); // 'sqlite' unless DB_CONNECTION says otherwise

go deeper

for a junior

Recall that DB_CONNECTION feeds config/database.php's default, that new apps use SQLite, and that DB::connection('name') picks another connection.

for a middle

Explain how named connections are created lazily and cached, how DB_URL replaces separate variables, and how a model pins its connection.

for a senior

Show that connections are independent, so transactions never span them, and diagnose environment changes hidden by cached configuration.

for a principal

Weigh whether a second database belongs behind its own connection in this app or behind a separate service boundary.

## Where the default comes from Laravel reads its database settings from **`config/database.php`**. Two keys matter most: - **`default`** names the connection used whenever code does not ask for a specific one. In the Laravel 13 skeleton it is `env('DB_CONNECTION', 'sqlite')`. - **`connections`** is an array of named connection definitions. The skeleton ships `sqlite`, `mysql`, `mariadb`, `pgsql` and `sqlsrv`, each reading its details from environment variables. The skeleton's `.env.example` sets `DB_CONNECTION=sqlite` and leaves `DB_HOST`, `DB_PORT`, `DB_DATABASE`, `DB_USERNAME` and `DB_PASSWORD` commented out. The `sqlite` connection uses `DB_DATABASE` when set and otherwise `database_path('database.sqlite')`, a file the installer creates. So a brand-new app runs migrations and serves requests with no database server at all. ## Switching the default To move an app to PostgreSQL, change the environment, not the code: ```ini DB_CONNECTION=pgsql DB_HOST=127.0.0.1 DB_PORT=5432 DB_DATABASE=coffee DB_USERNAME=app DB_PASSWORD=secret ``` Every connection also reads **`DB_URL`**. When a managed provider hands you one URL such as `pgsql://app:[email protected]:5432/coffee`, setting `DB_URL` supplies the driver, host, credentials and database in one variable. Because these values reach the app through `config/database.php`, a production deploy that caches configuration must re-cache after changing them. ## Using a second connection Many apps talk to more than one database: a reporting replica, a legacy system, a separate analytics store. Add a named entry to `connections`, then ask for it by name: ```php use Illuminate\Support\Facades\DB; $rows = DB::connection('legacy')->table('members')->where('active', 1)->get(); DB::connection('legacy')->transaction(function () { // statements here run on the legacy connection only }); ``` Useful facts about `DB::connection()`: 1. **Called without a name**, it returns the default connection. `DB::table()` is shorthand for `DB::connection()->table()`. 2. **Connections are created lazily** and cached by name for the rest of the process, so asking twice returns the same object and does not reconnect. 3. **Each connection is independent**: a transaction opened on the default connection does not cover statements sent through `DB::connection('legacy')`. 4. **An unknown name throws** an `InvalidArgumentException`, which surfaces a typo at the first query. ## Eloquent models A model uses the default connection unless told otherwise. In Laravel 13 the idiomatic way to pin one is the `Illuminate\Database\Eloquent\Attributes\Connection` attribute, `#[Connection('legacy')]`, placed on the class; the older `protected $connection = 'legacy';` property still works. ## Pitfalls around connections - **SQLite in development, MySQL in production.** The default makes a fresh app easy to start, but SQL that works on SQLite, such as date functions or loose type comparisons, can behave differently on the production driver. Run the test suite against the production driver before relying on it. - **Foreign keys on SQLite.** The skeleton's `sqlite` connection enables foreign key constraints through `DB_FOREIGN_KEYS`, which defaults to `true`; turning it off hides integrity errors that MySQL or PostgreSQL would raise. - **Hard-coded names.** Code that calls `DB::connection('mysql')` breaks when the default moves to `pgsql`. Use the default connection unless the second database is genuinely separate, and name that one after its role, such as `legacy` or `reporting`. ## Summary | Question | Answer in Laravel 13 | |---|---| | Default driver in a new app | SQLite | | Where it is chosen | `config/database.php` `default`, from `DB_CONNECTION` | | SQLite file location | `database/database.sqlite` unless `DB_DATABASE` is set | | Query another connection | `DB::connection('name')->table(...)` | | Pin a model to a connection | `#[Connection('name')]` or `$connection` | ## Why interviewers ask The question checks that a candidate knows configuration flows from environment variables through `config/database.php`, that the default changed to SQLite for new apps, and that a connection is a named, independent object. That last point matters later when transactions, read replicas and multi-database reports enter the conversation.

  • You set DB_CONNECTION=pgsql in production but queries still hit SQLite. What would you check first?
    Whether configuration is cached: after `php artisan config:cache`, the cached array is used and `.env` changes are ignored until the cache is rebuilt. Then check that `DB_CONNECTION` is set in the real environment of the PHP process, and that `config('database.default')` reports `pgsql` in `php artisan tinker` on that server.
  • Does DB::transaction() on the default connection protect writes made through DB::connection('legacy')?
    No. A transaction belongs to one connection object and its PDO handle. Writes sent through another named connection run in that connection's own autocommit mode or its own transaction. If both must succeed together, you need a design that tolerates partial failure, because Laravel does not coordinate transactions across connections.

saying these in an interview costs you the question

  • Says a new Laravel 13 app defaults to MySQL
  • Edits config/database.php values instead of environment variables
  • Thinks DB::connection('x') opens a new PDO on every call
  • Believes one DB::transaction() spans all configured connections
  • Expects a missing connection name to fall back to the default