DEV Community

Cover image for Introducing BioseqDB
BioseqDB
BioseqDB

Posted on Originally published at bioseqdb.com AI-assisted

Introducing BioseqDB

BioseqDB is a PostgreSQL extension for storing, indexing and searching biological sequences with SQL. Combine genomic matches with relational data using compact sequence types and columnar storage!

I wanted to keep sequences and their metadata together. If a sample has an organism, collection date or patient identifier, those values should be ordinary columns beside its DNA. Searching for a similar sequence should fit into the same query as filtering those columns.

Load FASTA or FASTQ and metadata into a BioseqDB table, then combine metadata filters and sequence alignment in one SQL query.

How it started

This project required several years of exploration and experiments. I began without a formal background in computational biology, thus learning the field was part of the research.

  • 2021–2022: Working with large GISAID datasets made FASTA files hard to manage. I proposed the database idea in May 2021 and directed a team prototype that connected BWA-MEM to PostgreSQL in May 2022.
  • 2023–2024: I wrote a Python aligner and then improved it, learning how the algorithms work along the way.
  • December 2025–2026: The current BioseqDB began with minimap2 and columnar storage. Custom seeding and chaining, indexes, sequence slices and end-to-end benchmarks followed.

The current BioseqDB is a separate project, designed and written by me. It contains no code or intellectual property from the early BWA-MEM integration experiments. The introduction and full timeline have more of the story.

Two queries to get a feel for it

These examples use the three synthetic samples from the SQL walkthrough. The samples table has ordinary metadata columns and a bioseq.seq column. USING bioseq selects the sequence-aware storage.

First, read metadata and a small piece of DNA. bioseq.len gives the sequence length; [:16] takes its first sixteen bases.

SELECT patient_name, bioseq.len(seq) AS bases,
  seq[:16]::text AS prefix
FROM samples
WHERE age >= 30
ORDER BY age DESC;
Enter fullscreen mode Exit fullscreen mode

Result · 2 rows

patient_name bases prefix
Ben 512 ACAAAAAGGGGCTTTC
Anna 4096 AAAGAGTAGATCGTAG

Now search those samples for Ben's sequence, stored in row 2. mmsearch performs the alignment; bioseq.score and bioseq.cigar describe each match.

SELECT t.patient_name,
  bioseq.target_start(t.seq) AS start,
  bioseq.score(t.seq) AS score,
  bioseq.cigar(t.seq) AS cigar
FROM samples AS t, samples AS q
WHERE t.age >= 30 AND q.id = 2
  AND mmsearch(t.seq, q.seq::bioseq.seq('dna4', 64))
ORDER BY t.id, start;
Enter fullscreen mode Exit fullscreen mode

Result · 3 rows

patient_name start score cigar
Anna 256 1024 512M
Anna 2304 1024 512M
Ben 0 1024 512M

Anna has two occurrences and Ben has one. These are exact matches, so each CIGAR is 512M. Alignment can also handle differences between sequences: substitutions, insertions and deletions. The alignment chapter explains how seeding, chaining and base alignment fit together.

Where it fits beside existing tools

BioseqDB builds on ideas from existing aligners, especially minimap2. The difference I wanted was the workflow: keep the data in PostgreSQL and combine sequence search with SQL filters and joins.

Tool Main focus
minimap2 Mapping reads and aligning nucleotide sequences against a reference.
BLAST Finding local sequence similarity in sequence databases.
Winnowmap Long-read mapping, including repetitive regions.
LexicMap Nucleotide alignment against large collections of prokaryotic genomes.
BioseqDB Storing sequences beside relational metadata and running alignment inside SQL.

In my benchmarks, the preferred CPU configuration was typically 3–8× faster than minimap2 when a prepared reference index was available. Without that index, BioseqDB was usually slower than minimap2. These tests used 1,024 synthetic queries against one 2 or 4 Gbp reference, not a collection of real genomes. Several external tools also needed the reference split into smaller records, so the measurement details matter when comparing them.

There is still work to do. The current GPU paths were slower than the CPU paths in these measurements, and indexing has known limitations. This first release is experimental software.

Try the Docker image

The image already includes PostgreSQL and BioseqDB. This is the Ubuntu 26.04 / PostgreSQL 19 prerelease image from the quick start:

docker run -d --name bioseqdb-demo \
  -e POSTGRES_PASSWORD=demo-change-me \
  -p 127.0.0.1:55432:5432 \
  styczynski/bioseqdb:0.1.0-alpha.1-pg19-ubuntu26.04
Enter fullscreen mode Exit fullscreen mode

Wait until PostgreSQL is ready, then open its SQL prompt:

until docker exec bioseqdb-demo pg_isready -h 127.0.0.1 -U postgres; do sleep 1; done
docker exec -it -u postgres bioseqdb-demo psql -U postgres -d postgres
Enter fullscreen mode Exit fullscreen mode

Follow the walkthrough to create the sample table, load a FASTA file and try the queries above. I would like to hear how it works with your data: open an issue or contact me.


Please check my OS project - BioseqDB.

Read this post on BioseqDB · Read on Medium · Follow BioseqDB on LinkedIn.

Top comments (0)