ramsql: an in-memory SQL engine for Go test suites
In-memory SQL engine in Go sql/driver for testing purpose
At a glance
- What is it?
- RamSQL is a Go library that registers itself as a database/sql driver and keeps every engine in memory, so a Go test can execute real SQL against a throwaway dataset without a PostgreSQL server, setup scripts or credentials. One DataSourceName per test gives full isolation. The SQL coverage is broad but incomplete, and the gaps are documented in the project itself.
- Who is it for?
- ramsql fits Go projects whose unit tests exercise SQL through database/sql and where standing up a real server per test run is the main source of friction. It does not fit code that depends on foreign keys, outer joins, explicit transaction control, JSON operators or B-Tree indexes, since the project's own feature table marks those as missing.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 21 days ago.
- What is it written in?
- Mainly Go, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The point where unit tests turn into infrastructure
The README describes the problem in a way every Go developer will recognise. Unit testing in Go is simple, create a foo_test.go file, import testing and run go test ./..., but then there are SQL queries, constraints and CRUD, and suddenly you need a PostgreSQL instance, setup scripts, and nothing is easy any more. RamSQL's stated purpose is to avoid setup, DBMS installation and credential management for as long as possible. That framing puts it squarely in the test suite rather than in production, and the repository description says so as well, an in-memory SQL engine in Go sql/driver for testing purposes. The audience is a team that has already decided its application layer speaks SQL through database/sql, and wants the tests to exercise that layer without a database. It is not a general purpose database, and it is not trying to be one.
Isolation comes from naming the engine
The isolation model is the cleverest part of the design and it is worth understanding precisely. A unique engine is tied to a single sql.DB with as many sql.Conn as needed, providing a unique DataSourceName. In practice that means the DataSourceName string is not a host and a password, it is the name of the in-memory engine, and two tests that open the same name share the same data while tests using different names are completely separate. The README sums it up as one DataSourceName per test and full test isolation in no time. The opening call is ordinary database/sql code, with the driver name `ramsql` and the test name as the DataSourceName:
db, err := sql.Open("ramsql", "TestLoadUserAddresses")
if err != nil {
t.Fatalf("sql.Open : Error : %s\n", err)
}
defer db.Close()Because the engine lives in the process, a test can create tables, insert rows, run a join and assert on the result with no server, no migration step and no cleanup beyond closing the handle. The trade is that nothing is shared between test functions unless they deliberately agree on a name.
What the SQL engine supports, and what it does not
The README carries a feature table listing the objectives for v1.0.0, with a separate column for parsing and one for implementation, and that distinction is the honest signal of where the engine stands. Parsed and implemented: tables, schemas, CREATE, PRIMARY KEY, DEFAULT, INSERT, UNIQUE, SELECT, backtick and quote quoting, COUNT, MAX, ORDER BY, UPDATE, DELETE, DROP, INNER JOIN, timestamp, now(), gen_random_uuid(), OFFSET, index, hash index and transactions. Marked as not implemented: FOREIGN KEY, OUTER JOIN, BEGIN and COMMIT, B-Tree index, JSON and AS. Reading that list tells you exactly which queries will pass and which will not. Foreign keys and outer joins are the two that most often surprise people, because a production schema and its test fixture are usually written with both. The engine also skips explicit transaction control even though transactions appear in the table, so a test cannot rely on rollback semantics to undo a failed setup.
The ramsql binary for checking a schema
Besides the driver, the project ships a command line binary that is useful on its own. The scenario the README describes is a SQL file describing an application structure, and the need to check that it is valid:
CREATE TABLE IF NOT EXISTS address (id BIGSERIAL PRIMARY KEY, street TEXT, street_number INT);
CREATE TABLE IF NOT EXISTS user_addresses (address_id INT, user_id INT);The binary is installed with the same module path and then reads statements from standard input, reporting the result of each one and the exit status:
$ go install github.com/proullon/ramsql
$ ramsql < schema.sql
ramsql> Query OK. 1 rows affected
ramsql> Query OK. 1 rows affected
$ echo $?
0That makes it possible to run a schema file through the same parser the tests use, which is a cheap way to catch a syntax mistake before it lands in a fixture. The `examples/` directory holds small SQL files for counting, joining and selecting, which are convenient starting points for a schema of your own.
Adding RamSQL to a Go project
Installation is a single module fetch:
go get github.com/proullon/ramsqlThe driver is then imported for its side effect in the test file, and the test proceeds as an ordinary database/sql test. The README's example creates its tables and rows with a batch of statements executed in a loop, including a `BIGSERIAL PRIMARY KEY` column and multi-line INSERT statements with accented and apostrophised street names, which is a fair illustration of how much SQL dialect the engine copes with. The module path is `github.com/proullon/ramsql`, the `go.mod` requires Go 1.20, and the README closes the section by making the point that there is no need for a running PostgreSQL or a setup step, that tests are isolated, and that they stay compliant with the standard go tooling.
How the pieces are laid out
The repository is split in a way that mirrors the public surface. The `driver/` directory holds the database/sql driver registration, which is why the test file imports `github.com/proullon/ramsql/driver` with a blank identifier, and that import is what makes the name `ramsql` available to `sql.Open`. The `engine/` directory contains the SQL engine itself, the `cli/` directory the command line front end, and `main.go` the binary entry point. `go.mod` declares Go 1.20 and pulls in a small set of dependencies, including a pure Go SQLite implementation, gorp, google/uuid, the exp package, and the GORM ORM with its PostgreSQL driver. The presence of GORM and the PostgreSQL driver in the dependency list is a hint about direction, since it suggests the project is aiming at compatibility with the ORM and database layers that Go services typically use. The Makefile provides the usual local targets, with install, test running go test with a ten second timeout, a bench target that pipes results through benchstat, a coverage report target, and a docs target that serves pkgsite locally.
Where RamSQL is the wrong tool
Three boundaries decide whether this belongs in your project. The first is the SQL dialect, and the feature table settles it: if your queries use foreign keys, outer joins, explicit BEGIN and COMMIT, JSON operators or the AS clause, the engine cannot run them. The second is scope. This is an in-memory engine for a test suite, so there is no durability, no concurrency story that resembles a real server, and no point pretending otherwise. A team that wants a lightweight database for development or a demo application is looking at a different project. The third is maturity and cadence. The tagged releases are all in the 0.1.x range, v0.1.2 in August 2023, v0.1.3 in October 2023 and v0.1.4 in July 2024, while the last push was on 2026-10-02, so the tree is receiving work that has not yet produced a new tag. The licence is BSD-3-Clause, with the LICENSE file at the repository root, which is a permissive choice for a test dependency and removes the licence question that a copyleft dependency would raise in a commercial codebase. The build badge in the README still points at a Travis CI URL, which is a small signal about how much of the original scaffolding is still in place.
Editorial conclusion
ramsql fits Go projects whose unit tests exercise SQL through database/sql and where standing up a real server per test run is the main source of friction. It does not fit code that depends on foreign keys, outer joins, explicit transaction control, JSON operators or B-Tree indexes, since the project's own feature table marks those as missing. Before adopting it, read the feature table against the SQL your tests actually execute, confirm your Go toolchain meets the 1.20 requirement in go.mod, and keep the latest tagged release v0.1.4 in mind when the last push on 2026-10-02 changes behaviour in your favour.
Frequently asked questions
How do I install ramsql in a Go project?
Run go get github.com/proullon/ramsql, then import the driver for its side effect with _ "github.com/proullon/ramsql/driver" in your test file. The module requires Go 1.20.
How does ramsql keep tests isolated?
A unique engine is tied to a single sql.DB and identified by its DataSourceName, so opening the driver with a different name gives a separate in-memory engine. The README summarises it as one DataSourceName per test and full test isolation.
Does ramsql support foreign keys and outer joins?
No. The project feature table marks FOREIGN KEY and OUTER JOIN as not implemented, along with BEGIN, COMMIT, B-Tree index, JSON and AS. INNER JOIN, transactions, hash index, ORDER BY, COUNT and MAX are supported.
Can I use ramsql to validate a SQL schema file?
Yes. The project ships a ramsql binary, installed with go install github.com/proullon/ramsql, that reads SQL from standard input, so you can pipe a schema file in and see the result of each statement.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/proullon-ramsql)Was this useful?