A fresh Laravel install creates 7-8 tables depending on your packages. The core ones are users, password_resets, failed_jobs, and personal_access_tokens. The cache, sessions, jobs, and batches tables are only created if you run the corresponding Artisan commands. None of them are sacred -- you can rename, extend, or replace any of them.
The core tables
users
| Column | Type | What it means |
|---|---|---|
id |
bigint (PK) | Auto-incrementing primary key. |
name |
varchar(255) | User's display name. |
email |
varchar(255) | Unique email address. |
email_verified_at |
timestamp | When email was verified. Null if unverified. |
password |
varchar(255) | Hashed password (bcrypt). Never store plain text. |
remember_token |
varchar(100) | Token for "remember me" functionality. |
created_at |
timestamp | Registration time. |
updated_at |
timestamp | Last profile update. |
password_resets
| Column | Type | What it means |
|---|---|---|
email |
varchar(255) | The email requesting a reset. |
token |
varchar(255) | The reset token (hashed). |
created_at |
timestamp | When the token was generated. |
This table is self-cleaning -- old tokens are garbage collected.
failed_jobs
| Column | Type | What it means |
|---|---|---|
id |
bigint (PK) | Auto-incrementing ID. |
uuid |
varchar(255) | Unique identifier for the job. |
connection |
text | Queue connection that failed. |
queue |
queue name | Which queue the job was on. |
payload |
longText | The job's serialized data. |
exception |
longText | The full exception stack trace. |
failed_at |
timestamp | When it failed. |
Use this table to debug failed queue jobs. The exception column has the full stack trace.
personal_access_tokens
Created by Laravel Sanctum for API token authentication.
| Column | Type | What it means |
|---|---|---|
id |
bigint (PK) | Auto-incrementing ID. |
tokenable_type |
varchar(255) | The model this token belongs to (e.g., App\Models\User). |
tokenable_id |
bigint | The ID of that model. |
name |
varchar(255) | Token name (e.g., "Mobile App"). |
token |
varchar(60) | The hashed token value. |
abilities |
text | JSON array of allowed abilities (e.g., ["*"]). |
last_used_at |
timestamp | When the token was last used. |
expires_at |
timestamp | When the token expires (null = never). |
Optional tables
sessions
Created by php artisan session:table. Stores HTTP session data in the database instead of files.
| Column | Type | What it means |
|---|---|---|
id |
varchar(255) (PK) | Session ID (from the cookie). |
user_id |
bigint (FK) | The user this session belongs to. Null for guests. |
ip_address |
varchar(45) | Client IP. |
user_agent |
text | Browser user agent string. |
payload |
longText | Serialized session data. |
last_activity |
integer | Unix timestamp of last activity. |
cache
Created by php artisan cache:table. Stores key-value cache entries in the database.
| Column | Type | What it means |
|---|---|---|
key |
varchar(255) (PK) | Cache key. |
value |
longText | Serialized cache value. |
expiration |
integer | Unix timestamp when it expires. |
jobs
Created by php artisan queue:table. Stores pending queue jobs.
| Column | Type | What it means |
|---|---|---|
id |
bigint (PK) | Auto-incrementing ID. |
queue |
varchar(255) | Queue name. |
payload |
longText | Serialized job data. |
attempts |
integer | How many times it's been tried. |
reserved_at |
integer | When it was reserved by a worker. |
available_at |
integer | When it can be picked up. |
created_at |
integer | When it was dispatched. |
batches
Created by php artisan queue:batches-table. Tracks batch progress for parallel job processing.
| Column | Type | What it means |
|---|---|---|
id |
bigint (PK) | Auto-incrementing ID. |
name |
varchar(255) | Batch name. |
total_jobs |
integer | Total jobs in the batch. |
pending_jobs |
integer | Jobs still to run. |
failed_jobs |
integer | Jobs that failed. |
failed_job_ids |
longText | JSON array of failed job IDs. |
options |
longText | Serialized batch options. |
cancelled_at |
timestamp | When cancelled (null if not). |
created_at |
timestamp | When the batch was created. |
finished_at |
timestamp | When the batch completed. |
What to change
-
Add a
rolecolumn tousersfor role-based access. -
Add a
phone_numbercolumn for SMS auth. -
Add an
avatar_urlcolumn for profile pictures. -
Rename
password_resetstopassword_reset_tokens(Laravel 8+ convention).
What to leave alone
- Don't modify the
failed_jobs.exceptioncolumn -- it needs to hold full stack traces. - Don't remove
personal_access_tokens.tokenable_type-- it's a polymorphic relation. - Don't add indexes to
cache.key-- it's already the primary key.
FAQ
Does Laravel create all these tables automatically?
No. Only users, password_resets, and failed_jobs are created by php artisan migrate. The others (sessions, cache, jobs, batches) require separate Artisan commands.
Can I use Redis instead of the database tables?
Yes. Laravel supports Redis for sessions, cache, and queues out of the box. Switch your .env driver to redis and the database tables become unnecessary.
What's the difference between password_resets and password_reset_tokens?
Same table, different names. Laravel 8+ renamed it to password_reset_tokens. If you're on an older version, it's still password_resets.
How do I visualize my Laravel schema?
Use dbdiagramr -- paste your connection string and get a visual schema of all your Laravel tables.

Top comments (0)