jgamboa / laravel-aurora-dsql
Laravel driver for Amazon Aurora DSQL: IAM token auth, DSQL-compatible schema builder (inline PK/FK, ASYNC indexes, identity) and migration helpers.
v0.1.1
2026-10-09 00:40 UTC
Requires
- php: ^8.2
- awslabs/aurora-dsql-pdo-pgsql: ^0.1.1
- illuminate/database: ^12.0|^13.0
- illuminate/support: ^12.0|^13.0
Requires (Dev)
- orchestra/testbench: ^10.0|^11.0
- phpunit/phpunit: ^11.0|^12.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Laravel (12+) database driver for Amazon Aurora DSQL.
- Connects with an IAM auth token through the official
awslabs/aurora-dsql-pdo-pgsqlconnector (SSLverify-full, OCC retries). - DSQL-compatible schema builder: regular Laravel migrations just work.
primary()andforeign()/constrained()are emitted inline inCREATE TABLE.index()/unique()→CREATE [UNIQUE] INDEX ASYNC, waiting for the index build to finish.id()/increments()→bigint generated by default as identity (cache 65536).- No schema transactions (DSQL allows a single DDL statement per transaction).
Schema::getTables(),db:show,db:wipeandmigrate:freshwork.
DsqlMigrationbase class for raw SQL migrations.
Installation
composer require jgamboa/laravel-aurora-dsql
The service provider is auto-discovered. Add a connection to config/database.php:
'dsql' => [ 'driver' => 'dsql', 'host' => env('DSQL_HOST'), // xxxx.dsql.us-east-1.on.aws 'region' => env('AWS_REGION', 'us-east-1'), 'username' => env('DSQL_USER', 'admin'), // 'admin' => dsql:DbConnectAdmin; other roles => dsql:DbConnect 'database' => 'postgres', // DSQL has a single database per cluster 'profile' => env('DSQL_PROFILE'), // local AWS profile (e.g. SSO). Leave empty on Lambda/EC2/ECS 'sslrootcert' => env('DSQL_SSLROOTCERT', 'system'), // 'system' requires libpq 17+ 'occ_max_retries' => 3, 'wait_for_indexes' => true, // wait for CREATE INDEX ASYNC jobs 'prefix' => '', 'prefix_indexes' => true, 'search_path' => 'public', ],
Usage
// A regular migration (no raw SQL) return new class extends Migration { protected $connection = 'dsql'; public function up(): void { Schema::create('products', function (Blueprint $table) { $table->uuid('id')->primary(); $table->foreignUuid('category_id')->constrained()->cascadeOnDelete(); $table->string('sku')->unique(); $table->timestamps(); }); } };
// Model: UUID v7 primary keys with HasUuids (Laravel 12+) class Product extends Model { use HasUuids; protected $connection = 'dsql'; }
Transactions with retries on OCC conflicts (SQLSTATE 40001):
DB::connection('dsql')->transaction(fn () => /* ... */, attempts: 3);
DSQL limitations (verified against a live cluster)
| Not supported | Alternative |
|---|---|
| Adding a PK / FK / UNIQUE / CHECK to an existing table | Declare them in Schema::create(); for unique use ->unique() (an index) |
ADD COLUMN with DEFAULT, NOT NULL or a FK |
Add it nullable → SET DEFAULT → backfill |
->change() (changing a column type), SET NOT NULL |
New table + copy + rename |
| Nested transactions (SAVEPOINT) | Avoid DB::transaction() inside another one |
TRUNCATE |
delete() |
Temporary tables, triggers, plpgsql, extensions, advisory locks, sharedLock() |
— |
| Full-text search with a language config | Only simple is available |
CREATE DATABASE |
One cluster per database |
Supported: lockForUpdate, upsert (needs a unique index), JSON/JSONB, CTEs, window functions, views, sequences, language sql functions.
Operational notes: connections last at most 60 minutes (long-running processes must reconnect); the IAM token is signed locally (no network call).
Testing
vendor/bin/phpunit --testsuite Unit DSQL_HOST=xxxx.dsql.us-east-1.on.aws DSQL_PROFILE=my-profile vendor/bin/phpunit --testsuite Integration
License
MIT