Skip to content

Support ecto_libsql (libSQL) as an alternative adapter#212

Open
AlanMcCann wants to merge 1 commit intoash-project:mainfrom
AlanMcCann:libsql-adapter-support
Open

Support ecto_libsql (libSQL) as an alternative adapter#212
AlanMcCann wants to merge 1 commit intoash-project:mainfrom
AlanMcCann:libsql-adapter-support

Conversation

@AlanMcCann
Copy link
Copy Markdown

@AlanMcCann AlanMcCann commented Apr 27, 2026

libSQL (github.com/tursodatabase/libsql) is an open-source fork of SQLite that adds ALTER COLUMN, native vector search (DiskANN), and embedded replicas while maintaining full backwards compatibility with the SQLite file format and API.

Changes:

  • verify_repo: accept Ecto.Adapters.LibSql alongside SQLite3
  • repo: make adapter configurable via :adapter option (defaults to Ecto.Adapters.SQLite3 for backwards compatibility)
  • data_layer: add EctoLibSql.Error handlers (guarded by Code.ensure_loaded? so ecto_libsql remains optional)
  • mix.exs: add ecto_libsql as optional dependency
  • tests: 6 tests covering adapter acceptance, backwards compatibility, and constraint message parsing

Usage:

use AshSqlite.Repo,
  otp_app: :my_app,
  adapter: Ecto.Adapters.LibSql

All existing behavior is unchanged when using Ecto.Adapters.SQLite3. The :adapter option defaults to Ecto.Adapters.SQLite3 when not specified.

Tested against a production Ash application: 5877 tests, 5872 passed, 5 failures unrelated to the adapter change (DBConnection ownership race conditions).

Contributor checklist

Leave anything that you believe does not apply unchecked.

  • I accept the AI Policy, or AI was not used in the creation of this PR.
  • Bug fixes include regression tests
  • Chores
  • Documentation changes
  • Features include unit/acceptance tests
  • Refactoring
  • Update dependencies

libSQL (github.com/tursodatabase/libsql) is an open-source fork of
SQLite that adds ALTER COLUMN, native vector search (DiskANN), and
embedded replicas while maintaining full backwards compatibility
with the SQLite file format and API.

Changes:
- verify_repo: accept Ecto.Adapters.LibSql alongside SQLite3
- repo: make adapter configurable via :adapter option (defaults
  to Ecto.Adapters.SQLite3 for backwards compatibility)
- data_layer: add EctoLibSql.Error handlers (guarded by
  Code.ensure_loaded? so ecto_libsql remains optional)
- mix.exs: add ecto_libsql as optional dependency
- tests: 6 tests covering adapter acceptance, backwards
  compatibility, and constraint message parsing

Usage:

    use AshSqlite.Repo,
      otp_app: :my_app,
      adapter: Ecto.Adapters.LibSql

All existing behavior is unchanged when using Ecto.Adapters.SQLite3.
The :adapter option defaults to Ecto.Adapters.SQLite3 when not
specified.

Tested against a production Ash application: 5877 tests, 5872
passed, 5 failures unrelated to the adapter change (DBConnection
ownership race conditions).
@zachdaniel
Copy link
Copy Markdown
Contributor

This is cool. Does libSQL also solve the semantics around parallel transactions such that they wait/go in sequence the way postgres does?

@AlanMcCann
Copy link
Copy Markdown
Author

Unfortunately not. libSQL inherits SQLite's single-writer model. One writer at a time, period. If two processes try to write simultaneously, one gets SQLITE_BUSY and has to retry. The busy_timeout setting (I have it at 5000ms in config) makes the second writer wait up to that duration for the lock to release. So in practice, writes serialize with a wait rather than an error. But it's not the same as PostgreSQL's MVCC where multiple transactions run concurrently and conflicts are resolved at commit time.

I have an application with per-user SQLite databases, so in practice it won't matter much and why I'm testing out deployment with this versio

Turso Database has it but is in beta and is missing ALTER TABLE which is a key reason (besides vector support) I'm testing out libSQL.

@zachdaniel
Copy link
Copy Markdown
Contributor

So I'm wondering if it would be realistic to add some CI only integration tests here. Or even to swap out the adapter at compile time for our existing tests and run them to ensure all the tests pass. Because right now we provide this as an option but aren't actually validating in our tests that it works.

@AlanMcCann
Copy link
Copy Markdown
Author

AlanMcCann commented Apr 28, 2026 via email

@zachdaniel
Copy link
Copy Markdown
Contributor

Yeah, I think option 1 is best 👍

@zachdaniel
Copy link
Copy Markdown
Contributor

I'll update the test matrix so you can pull main and try it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants