Open-source project
KarnerTh/mermerd avatar
KarnerTh/mermerd

mermerd: turns a live database schema into a Mermaid ER diagram

Create Mermaid-Js ERD diagrams from existing tables

619 stars50 forksGoMIT

At a glance

What is it?
mermerd is a Go tool that connects to PostgreSQL, MySQL, MSSQL or SQLite, reads the tables and constraints that exist, and writes a Mermaid-JS entity relationship diagram, with an interactive terminal picker and YAML run configurations for pipelines. It suits a team whose schema is the truth and whose documentation lags behind it, and it produces a snapshot of what the database enforces, not a picture of what the application means.
Who is it for?
Adopt mermerd if your documentation is stale because the schema keeps moving, and you want a diagram that is generated from the database rather than maintained by hand in a pull request. Do not adopt it to document relationships the database does not enforce, because every line in the output comes from a key or a constraint the engine reports, and it is a snapshot rather than a live view.
Can I use it commercially?
Yes. MIT 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 42 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

Documentation that is generated rather than maintained

mermerd creates Mermaid-JS entity relationship diagrams from existing tables, and the README explains the motivation in unusually plain terms: documenting stuff and keeping it updated is hard and tedious, but having the right documentation can help to make the right decisions.

That is the whole argument for the tool. An ER diagram in a repository drifts. A new column lands, a foreign key is added in a migration, and the picture in the wiki is now a lie. mermerd sidesteps the maintenance question by reading the schema from the database itself, so the diagram cannot describe a schema that does not exist.

The stated purpose is narrower than documentation in general. Mermerd was designed to be able to export an existing database schema in a format that can be used to prototype and plan new features based on the existing schema. The output is an ERD in Mermaid-JS format that can easily be updated and extended, which is what makes it usable in a repository: the file is text, it diffs, and it renders in a markdown viewer.

The project is written in Go, licensed under MIT, and the author publishes a changelog so that you can see what changed between versions, which is the first thing to read when a diagram generator has altered its output format.

Four database engines, one set of flags

mermerd supports PostgreSQL, MySQL, MSSQL and Sqlite3, and the module file shows the driver for each: jackc/pgx/v5 for PostgreSQL, go-sql-driver/mysql for MySQL, microsoft/go-mssqldb for MSSQL and modernc.org/sqlite for SQLite, the last of which is a pure Go implementation rather than a cgo binding to the C library.

On top of the drivers there is a terminal UI, and the dependencies for it are visible too: AlecAivazis/survey for the interactive prompts with its multiselect and search, briandowns/spinner for the wait states, fatih/color for the output, sirupsen/logrus for logging, spf13/cobra for the command line and spf13/viper for configuration, plus stretchr/testify for the tests.

The feature list adds two things that matter for real schemas. You can select from the available schemas, and you can select only the tables you are interested in, and you can show only the constraints you are interested in. A database with four hundred tables produces an unreadable diagram, and the selection steps are what make the output usable.

The output format is configurable as well. It can be plain Mermaid syntax, or it can be enclosed in Mermaid backticks, which the documentation says is needed for use in a markdown viewer such as GitHub markdown. That single flag is the difference between a file you paste into a diagram renderer and a file you commit next to your documentation.

The four step flow, from connection string to diagram

How it works is described in four steps, and the order matters because each step can be done from a flag or from the interactive prompt.

First you specify the connection string, either as a parameter or through the interactive CLI. Second you specify the schema that should be used, again by parameter or interactively. Third you select the tables you are interested in, with a multiselect where at least one table must be chosen. Fourth you get your current database schema in Mermaid-JS format.

That last phrasing, your current database schema, is the important one. mermerd reads the live database, so the diagram reflects what is in the database at the moment you run it, including any drift between the migrations in your repository and the tables that actually exist.

That cuts both ways and it is worth being clear about it. The diagram cannot be wrong about the schema, because it is read from the schema. But it also cannot tell you which of the foreign keys your application actually uses, or which tables are effectively dead, or how a polymorphic association was meant to work when the database only enforced it with a nullable column. The output is a faithful rendering of the constraints the engine reports, and nothing more.

The flags decide how much of the schema reaches the page

The flag list is long, and the flags fall into groups that map onto the questions you have when you look at a schema.

The connection and output flags are -c for the connection string, -o for the output file name, which defaults to result.mmd, --outputMode with the values file and stdout, and -e to enclose the output in Mermaid backticks. The schema flags are -s for a single schema, --useAllSchemas for all of them, --showSchemaPrefix to put the schema in the table name, and --schemaPrefixSeparator, which defaults to a dot, so you can have either public.customer or public_customer depending on what your diagram renderer can parse.

The table selection flags are --selectedTables, --useAllTables, and --ignoreTables, which supports regular expressions, which is the one to reach for when a handful of audit or migration tables are drowning out the rest.

The constraint flags are where the diagram gets interesting. --omitAttributeKeys drops the PK, FK and UK markers, --omitConstraintLabels drops the labels, and --relationshipLabels lets you substitute a different label for specific table relationships, which overrides omitConstraintLabels when specified. --showAllConstraints prints constraints of tables you did not select, and the documentation explains the cost: those tables appear with their table name only and no column information.

Finally, --showDescriptions takes a list of what to put in the description column, from notNull, enumValues and columnComments. The default output therefore shows primary keys, foreign keys and unique constraints, enum values for enum columns, column comments and NOT NULL constraints, and the flags let you take each of those away.

Two YAML files: a global default and a per run configuration

There are two configuration surfaces, and they solve different problems.

The global configuration file is a yaml file in your home directory called .mermerd, which has to be created yourself; the repository ships .mermerd.example as a starting point. You use it to set the options you want by default, for example enabling showAllConstraints for all runs, and to provide connection string suggestions that appear in the interactive CLI, reachable with the tab key. The example sets options such as showAllConstraints, encloseWithMermaidBackticks, outputFileName, debug, omitConstraintLabels, omitAttributeKeys, showDescriptions, showSchemaPrefix and schemaPrefixSeparator, and then lists four connection string suggestions for PostgreSQL, MySQL, SQL Server and SQLite.

The run configuration is the CI/CD mechanism. You can specify all the parameters needed for generating the ERD in a yaml file, and start mermerd with mermerd --runConfig yourRunConfig.yaml. The example run configuration, which the repository also ships as exampleRunConfig.yaml, sets the connection string, chooses between useAllSchemas and an explicit list of schemas, chooses between useAllTables and a list of selected tables, and then sets the additional flags, including outputMode: stdout, which is the one to use when the diagram is going to be written into a pipeline artifact rather than a file.

The --runConfig flag replaces the global configuration, so a run configuration is self-contained, and that is what makes the tool usable in a pipeline where nobody has a home directory.

Building it, testing it, and the mismatch in the Go requirement

Installation is through the Go toolchain, and the README states that it requires go version 1.21 or later:

sh
# install latest version
go install github.com/KarnerTh/mermerd@latest

# install specific version
go install github.com/KarnerTh/[email protected]

Alternatively you can download the right executable for your operating system from the Releases page and add it to your path to use it globally. The repository carries a .goreleaser.yml, which is what produces those per platform executables.

The go.mod is worth a second look, because it says go 1.24.0 with toolchain go1.24.3, which is a stricter requirement than the 1.21 in the README. There is also a godebug setting for x509negativeserial=1, which the module file explains with a link to an issue about the Microsoft SQL Server container image, so the MSSQL driver needed a compatibility setting.

The Makefile shows how the project is developed. The prepare-sqlite target builds a test database by concatenating three SQL files and piping them into the sqlite3 command line, the test-coverage target runs go test with coverage and renders an HTML report, and the create-mocks target runs mockery to regenerate the mocks in the mocks/ directory. There are also test-all and test-unit targets that pipe the test output into tparse, a test output parser, and a test-cleanup target that clears the test cache.

The repository layout follows the same shape as the code: analyzer/ for the schema analysis, database/ for the engine specific queries, diagram/ for the Mermaid rendering, presentation/ for the terminal UI, config/ for the configuration, cmd/ for the command, util/ for shared helpers, and test/ for the test suites.

Where mermerd is the wrong tool

Three limits follow from the mechanism, and the middle one is the one that decides most cases.

The first is that the diagram is a snapshot. It is generated from a database at a point in time, and nothing keeps it in step afterwards. In a pipeline you can regenerate it on a schedule or on a schema change, which is the point of the run configuration, but a diagram that is committed and left alone will go stale exactly like a hand written one, just more slowly.

The second is that the diagram can only show what the database enforces. Primary keys, foreign keys, unique constraints, NOT NULL and enum values are all real and all worth showing. A logical relationship that the application maintains without a foreign key is invisible, and so is a table that has been abandoned but never dropped. The documentation section on how mermerd determines the constraints exists precisely because that boundary is worth understanding before you publish a diagram and call it the model.

The third is that it is a generator, not a renderer. The output is Mermaid-JS text, so whatever renders Mermaid in your documentation pipeline has to be able to render an entity relationship diagram, and a diagram with many relationships can be unreadable in a viewer regardless of how well it was generated.

The alternative is the hand written diagram, and the difference in approach is the whole trade. A curated Mermaid file in your repository can express the relationships that matter to your team, including the ones with no foreign key, and it can be annotated with intent. What it cannot do is stay true, and keeping it true by hand is the tedious work mermerd was written to remove. For a schema with a dozen stable tables, the hand written diagram is better. For a schema that a migration touches every week, the generated one is the only version that is still true on Monday.

Editorial conclusion

Adopt mermerd if your documentation is stale because the schema keeps moving, and you want a diagram that is generated from the database rather than maintained by hand in a pull request. Do not adopt it to document relationships the database does not enforce, because every line in the output comes from a key or a constraint the engine reports, and it is a snapshot rather than a live view. Verify first that your database engine is one of the four supported ones, that the schema and table selection behave the way you expect for multi schema databases, and that the generated Mermaid renders in whatever tool your documentation pipeline uses.

Frequently asked questions

Which databases does mermerd support?

PostgreSQL, MySQL, MSSQL and Sqlite3. The drivers in the module file are pgx/v5 for PostgreSQL, go-sql-driver/mysql for MySQL, microsoft/go-mssqldb for MSSQL and modernc.org/sqlite, the pure Go SQLite implementation, for Sqlite3.

How do I install mermerd?

Through the Go toolchain with go install github.com/KarnerTh/mermerd@latest, or a specific version with go install github.com/KarnerTh/[email protected]. The README says Go 1.21 or later is required, while the module file declares go 1.24.0 with toolchain go1.24.3. You can also download a prebuilt executable from the Releases page and put it on your path.

How do I run mermerd in a CI/CD pipeline?

With a run configuration file, started as mermerd --runConfig yourRunConfig.yaml. The yaml sets the connection string, the schemas, the selected tables and the additional flags, and the example in the repository uses outputMode: stdout so the diagram goes to standard output rather than a file.

What can the mermerd diagram show?

Primary keys, foreign keys and unique constraints, enum values for enum columns, column comments and NOT NULL constraints. The showDescriptions flag chooses which of notNull, enumValues and columnComments appear in the description column, and showAllConstraints adds constraints of tables you did not select, which then appear with their table name only and no column information.

Where does mermerd keep its configuration?

In a yaml file called .mermerd in your home directory, which has to be created, with .mermerd.example in the repository as a model. It holds default options and connection string suggestions for the interactive CLI, and a run configuration passed with --runConfig replaces it entirely.

Official sources

  1. Issues
  2. KarnerTh/mermerd on GitHub
  3. License: MIT
  4. README
  5. Releases
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.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/karnerth-mermerd.svg)](https://hysenlabs.com/projects/karnerth-mermerd)

Was this useful?