How SeqDesk Works
SeqDesk is a self-hosted platform for taking a sequencing request from a researcher, tracking it through a sequencer, attaching the resulting FASTQ files, analysing them, and publishing the outcome to the European Nucleotide Archive. It runs as one Next.js process against one PostgreSQL database on hardware you control.
This page is the mental model the rest of the documentation assumes. If you read only one conceptual page, read this one.
Five nouns
Almost everything in SeqDesk is one of five things. Two of them have similar names and are the single most common source of confusion, so start there.
| Concept | Schema model | What it actually is |
|---|---|---|
| Sequencing Order | Order | The researcher’s request: the questionnaire answers, the sample list, the contact and billing details. Numbered ORD-YYYYMMDD-NNNN. |
| Sequencing Run | SequencingRun | The physical instrument run: run plan, barcode-to-sample assignment, Q30 and cluster-density QC, demultiplexing stats. |
| Sample | Sample | One biological sample. Belongs to exactly one sequencing order. Carries organism, taxonomy ID, title, and any custom or MIxS metadata. |
| Read | Read | A FASTQ file, or an R1/R2 pair, attached to one sample. Carries checksums, read counts, and a data class. |
| Study | Study | A scientific grouping of samples for analysis and for publication. Carries the MIxS checklist and the ENA project metadata. |
A Sequencing Order is not a Sequencing Run. The order is paperwork;
the run is an instrument. One order contains zero or more runs. The UI relabels
the Order model to “Sequencing Order”, but every identifier in the API,
the database and the URLs stays Order / orderId / orderNumber.
How they connect
Read this as a sentence rather than a diagram:
- A User owns many Sequencing Orders. Every order has exactly one owner
(
Order.userId), and that ownership is what the permission checks use. - A Sequencing Order contains many Samples (
Sample.orderId, cascade delete). Delete the order and its samples go with it. - A Sequencing Order contains zero or more Sequencing Runs
(
SequencingRun.orderId). A run’srunIdonly has to be unique within its order, soRUN-01can exist in two different orders. - A Sequencing Run links to Samples through
SequencingRunSample, which carries the barcode for that sample on that run. A barcode is unique per run, and a sample appears at most once per run. - A Sample has many Reads (
Read.sampleId, cascade delete). A read may optionally point back at the sequencing run it came off (Read.sequencingRunId) and at the pipeline run that produced it (Read.pipelineRunId). - A Sample belongs to at most one Study (
Sample.studyId, nullable). This is the constraint people trip over: assigning a sample to a second study moves it, it does not copy it. If you need the same physical material in two analyses, you need two samples. - A Study may draw its samples from several sequencing orders. That is the entire point of a study — it is the scientific unit, whereas the order is the administrative unit.
- A Pipeline Run targets either a study or an order
(
PipelineRun.targetTypeisstudyororder) and records the sample IDs it ran over. Its outputs become Assembly, Bin and Read rows linked back to the run.
The lifecycle, in the order it happens
1. A researcher raises a sequencing order
The researcher fills in the order wizard and submits. The order gets a number
in the form ORD-YYYYMMDD-NNNN (the counter restarts each day) and moves from
DRAFT to SUBMITTED.
Order status is a three-value ladder, not an enum in the database:
| Status | Meaning | Who can set it |
|---|---|---|
DRAFT | Being prepared. Samples are editable. | Created automatically |
SUBMITTED | Handed to the facility. Samples are frozen. | The owner, or an admin |
COMPLETED | Every sample has at least one read with a file. | Set automatically; an admin can set it manually |
A researcher may only make the one transition DRAFT → SUBMITTED; anything
else returns Invalid status transition. Facility admins may move an order
backwards.
COMPLETED is usually reached without anyone clicking anything: whenever a file
is assigned, SeqDesk re-checks the order, and if it is SUBMITTED, has at
least one sample, and every sample has a read with a file, it flips the order
to COMPLETED and writes the status note “Automatically completed - all samples
have sequencing files”.
2. The facility sequences the samples
Samples carry their own facility-side status, independent of the order status, so a facility can track progress per sample rather than per order:
WAITING → PROCESSING → SEQUENCED → QC_REVIEW → READY, with ISSUE as
the escape hatch. New samples start at WAITING.
If the facility uses the Sequencing Run surface, it also records the physical run: platform, instrument, run date, folder path, Q30 score, cluster density, pass-filter percentage, and the barcode each sample carried.
3. FASTQ files get attached to samples
There are three ways data reaches a sample. All three end with a Read row.
File scan (the default). After sequencing finishes, an admin opens the
order’s Sequencing Data area and uses the Associate view to browse the
configured data directory. SeqDesk lists candidate FASTQ files, recognises
_R1/_R2 (and _1/_2) naming to pair them, and the admin links them to
samples. This requires the order to be SUBMITTED or COMPLETED — attempting
it on a DRAFT order returns
Sequencing Order status 'DRAFT' does not allow file assignment.
Direct upload. Files can be uploaded into the order through the same
Sequencing Data area, tracked as SequencingUpload rows with an expected size
and a checksum, then promoted to reads.
Live MinKNOW stream ingest (Oxford Nanopore). For ONT runs an admin can
attach a running MinKNOW sequencing run to an order and have reads ingested
while MinKNOW writes them, matched to samples by barcode. A long-lived
stream-monitor daemon, running outside the web process, watches MinKNOW’s
output root. Configure it at Settings → MinKNOW Stream
(/admin/minknow-stream); drive an individual order from its
Sequencing Data → Stream view. If the daemon is not running, nothing is
ingested no matter how the configuration looks. The StreamRun,
StreamIngestedFile and StreamRunEvent records track each live session.
4. Reads are classified, and only cleaned reads are delivered
Every read carries a dataClass:
dataClass | Label in the UI | Meaning |
|---|---|---|
cleaned | Cleaned | Safe to hand to the requesting researcher. The default. |
raw | Raw / protected | Host or contaminant sequence may still be present. Never delivered. |
unknown | Unknown | Not yet classified. Treated as protected. |
Reads also carry isActive. A read-cleaning pipeline writes a new cleaned read
and marks the old one inactive with supersededByReadId pointing forward, so
the provenance chain survives.
This matters because of the delivery gate. A researcher cannot download
their own sequencing files until an admin explicitly publishes them. On the
order’s Sequencing Data → Overview there is a Delivery to user card with
a Make downloadable to user button; it stamps
Order.sequencingFilesPublishedAt. Until then, a researcher requesting the
delivery gets Sequencing files are not available for this sequencing order.
After publication they see only reads that are both cleaned and isActive,
plus sequencing artifacts explicitly marked visibility: "customer". The
button is disabled if there is nothing publishable — the API answers
No cleaned reads or customer-facing reports are available to publish.
Publication is reversible with Hide from user.
5. Samples are grouped into a study
A study is created by a researcher or an admin, given a title, description and
(optionally) a MIxS checklist, and then has samples assigned to it. The
checklist version is pinned at creation time (Study.mixsVersion) so that a
later registry update never retroactively rewrites the fields of an existing
study.
A study advances through two boolean flags rather than a status column:
readyForSubmission (with readyAt) means the metadata is complete enough to
publish, and submitted (with submittedAt and studyAccessionId) means it
has been registered with ENA.
6. Pipelines run over an order or a study
Pipelines are optional. The core application — orders, samples, studies, ENA submission — works with pipelines switched off, which is the default.
Each pipeline package declares which scopes it supports, and that decides where its launch button appears:
| Scope | Launched from | Bundled packages |
|---|---|---|
order | The order’s Analysis view | Simulate Reads, FASTQ Checksum, FastQC, NanoPlot, Read Cleaning |
study / samples | The study’s Analysis tab | MAG, Kraken2 + Bracken, Quality Overview, Study MultiQC, Study Demo Report, Submit to ENA |
Only a FACILITY_ADMIN can start a run; the create endpoint returns 403 for
anyone else. None of the bundled packages set userCanStart, so in a default
install researchers never launch anything.
A run moves pending → queued → running → completed / failed /
cancelled, gets a number like MAG-20240126-001, and executes either as a
local detached process or as a SLURM submission. See
Running a Pipeline for the launch mechanics
and Monitoring for how progress is tracked.
7. Results are published to the requesting researcher
Completing a run does not show it to the researcher who asked for the sequencing. Pipeline runs are visible to a non-admin only when both are true: they own the target study or order, and an admin has marked a run as final for that pipeline and target. The admin does this from the run’s menu with Use as final; the run then carries a Final badge, and Clear final reverses it. Exactly one run can be final per pipeline per target, so re-running MAG and marking the new run final silently replaces the old one in the researcher’s view.
Only completed runs can be marked final — otherwise the API answers
Only completed pipeline runs can be selected as final.
8. The study is submitted to ENA
With ENA Webin credentials configured, the study and its samples are registered
with the archive, and reads, assemblies and bins can follow. Accessions come
back and are written onto the SeqDesk records: Study.studyAccessionId,
Sample.sampleAccessionNumber and biosampleNumber, Read.runAccessionNumber
and experimentAccessionNumber.
Note which field becomes the ENA alias: SeqDesk sends Sample.sampleId — the
internal generated identifier, shaped S-<timestamp>-<random> — not the
human-facing Sample Alias field. See
ENA Submission for the full flow.
Who can do what
There are exactly two roles, stored as a plain string on User.role:
RESEARCHER (the default for self-registration) and FACILITY_ADMIN. There is
no project-level, per-study or per-department permission layer on top.
| Capability | RESEARCHER | FACILITY_ADMIN |
|---|---|---|
| Create sequencing orders | Yes | Yes |
| See other people’s orders | Only with department sharing on | All of them |
| Edit samples | Only while the order is DRAFT | Facility-only fields at any time |
| Delete a submitted order | Never | Only if the admin toggle allows it |
| Create studies, assign samples | Yes (own studies only) | Yes (all studies) |
| Attach FASTQ files to samples | No | Yes |
| Download sequencing files | Only after delivery is published | Yes |
| Start a pipeline run | No | Yes |
| See a pipeline run | Only runs marked Final on their own study or order | All runs |
| ENA submissions surface | Hidden from the sidebar | Yes |
Admin area (/admin/**) | No | Yes |
Department sharing is the one softener. With
access.departmentSharing enabled under Settings → Accounts → Access &
Sharing, a researcher sees every order belonging to a user in the same
department instead of only their own. It applies to orders only — studies stay
strictly per-owner regardless.
Architecture
SeqDesk is a single Next.js application that bundles the web UI, the REST API and pipeline orchestration into one process.
| Layer | Technology | Role |
|---|---|---|
| Frontend | React + Tailwind CSS | Interactive UI with live pipeline monitoring |
| API | Next.js route handlers | REST endpoints under /api/** |
| Database | PostgreSQL 14+ | Persistent storage via Prisma (SQLite is not supported) |
| Auth | NextAuth.js, credentials provider, JWT sessions | Email + password against the local User table |
| Pipelines | Nextflow, Conda-provisioned | Local process or SLURM submission |
You normally do not supply the database yourself. The installer reuses a local
PostgreSQL server it can administer, or creates and owns a private,
socket-only cluster under $HOME/.seqdesk/postgres that the install directory’s
start.sh starts before the app.
Configuration resolution
Configuration is merged from four layers, highest priority first:
- Environment variables — for deployment automation.
- Config file —
settings.jsonin the install root, writtenchmod 600and symlinked into the active release so there is exactly one config file. Installs created before the settings consolidation keep the legacyseqdesk.config.jsonname. - Database — runtime settings changed through the admin UI.
- Built-in defaults.
This lets you pin a value at deployment time while leaving the rest editable in
the UI. Settings → Info (/admin/settings) shows which layer each effective
value came from. See Configuration.
Modules
Nine optional modules add or remove whole field groups and behaviours: MIxS Metadata, External Funding & Grants, Cost Center & PSP, ENA Sample Fields, Sequencing Technology, Dynamic Study Definitions, AI Field Validation, Account Validation, Email Notifications. Toggle them at Settings → Modules.
Two things worth knowing: MIxS Metadata, AI Field Validation and ENA Sample Fields are on by default, and Sequencing Technology is always enabled and cannot be switched off. The module list itself is compiled into the build — you can turn modules on and off, but adding a new one requires code.
Self-hosted by design
- No cloud dependency. The database, the file storage and the pipeline execution are all local. Sequencing files are referenced by path on your own storage and are never uploaded to a remote service.
- Two optional outbound calls, both off by default: the telemetry heartbeat, and the hosted email relay. Both are documented and both can stay disabled.
- One command to install. Download
install.shand run it with--interactive; the globalseqdesknpm launcher runs the same script. See Installation. - Built-in updates with backup and rollback. See Updates & Maintenance.
SeqDesk assumes a closed, trusted network — an institutional intranet or a VPN. Read What SeqDesk doesn’t do (yet) before putting an instance on the public internet.