# Random Access to Genomic Data: How Indexing Works

Random access to genomic data is the ability to pull one region, one read, or one feature out of a file without reading every byte that precedes it. An index is the small companion file that makes this possible by recording where each region's records physically begin inside the stored byte stream.

That single idea is the difference between a workflow that finishes and one that stalls. Sequence archives, biobank summary statistics, and clinical variant stores have grown far faster than disk throughput. A collection of 1,092 human diploid genomes occupies about 6.7 TB as uncompressed FASTA and only about 700 MB after collection-aware compression [1]. Even at that compressed size, scanning the whole archive to answer a question about one locus would be wasteful. Indexing collapses the cost of a targeted question from "read the file" to "read a few kilobytes." This article explains the mechanism, the file formats, the command-line behavior, and the interpretation rules that let you tell a working index from a broken one.

## The Two Access Models

Sequential access reads a file from the first byte to the last. Every parser that streams FASTQ needs sequential access, because the quality string of read 4,000,000 cannot be located without counting the three reads before it. Sequential access is simple and cache-friendly, and it is the correct model for whole-file transformations such as alignment, variant calling, and quality trimming.

Random access jumps to a known position. The operating system exposes this as `seek()`, which moves a file pointer to a byte offset in constant time. The hard part is knowing which offset to seek to. A genomic file has no natural fixed record size, since reads differ in length and variants differ in representation, so the offset of "chr7 position 117,199,827" is not something you can compute from a formula. It has to be recorded in advance.

An index is that recording. It is not a copy of the data and it is not a cache. It is a lookup structure with two jobs: translate a genomic coordinate into a byte position, and narrow the search to the smallest set of records that could possibly overlap the query. Everything else in this article is an implementation detail of those two jobs.

Three kinds of keys are indexed in practice. Coordinate keys map a chromosome and a position range to offsets, which is what BAM, VCF, and BigWig indices do. Identifier keys map a stable name such as a gene ID or a transcript ID to offsets, which is what annotation toolkits build [2]. Statistic keys map a value range, such as a p-value band, to offsets, which is what summary-statistic indices add [3]. A well-designed index can serve more than one key type, but the underlying byte-position machinery is the same.

## Why Ordinary Compression Defeats Seeking

Raw FASTA and raw BAM are large, so nearly every genomic file in circulation is compressed. The default choice, gzip, is hostile to random access. A gzip file is one continuous DEFLATE stream. Each compressed symbol may reference previous output through a back-distance pointer, so decompression is inherently stateful. To inflate byte 40,000,000,000 you must first inflate bytes 0 through 39,999,999,999. There is no safe place to start in the middle, and therefore no place to seek to.

The fix is block compression. BGZF, the blocked gzip format used by BAM, CRAM containers, and tabix-indexed text, writes the data as a series of independent gzip members. Each member holds at most 65,536 bytes of uncompressed data and carries an extra header field that states the member's own compressed size. Because each member is self-contained, any member can be inflated without touching its predecessors. Because its compressed size is stored in its header, the next member's start offset is computable. The format is still valid gzip, so `gzip -d` can decompress a BGZF file, but only a BGZF-aware reader can start in the middle.

Block compression alone is not enough. You also need a way to name a position inside a compressed stream. The convention is the virtual offset, a 64-bit integer in which the high 48 bits give the compressed offset of the BGZF block and the low 16 bits give the byte offset inside that block once decompressed. Sixteen bits address 65,536 values, which matches the maximum uncompressed block size exactly, so no position is unrepresentable. A second lookup file, the `.gzi` index, stores the compressed offset corresponding to every 64 KB boundary of the uncompressed stream, letting a reader convert a plain uncompressed position into a block address when it has no virtual offset to begin with.

For formats that need position-based queries over text, BGZF is paired with a tabix index (`.tbi`), which is itself a BGZF file. For BAM the pairing is `.bai` or `.csi`. For a plain bgzipped FASTA or FASTQ the pairing may be only `.gzi`. The naming pattern matters in practice: a `.vcf.gz` without a `.tbi` is a sequentially accessible file that most region-query tools will refuse to touch, which is exactly the gap that motivated in-browser binary-search approaches for unindexed VCF [4].

## A Comparison of Index Types Across Formats

| Data file | Index file | Lookup structure | Smallest addressable unit | Typical query |
|--|--|--|--|--|
| FASTA | `.fai` | per-record offset plus line-length arithmetic | one base | `chr1:1-1000` |
| FASTQ | none standard, tool-specific | record or block directory, or reordered reads | one read | by ID or by reconstructed position |
| BAM | `.bai` or `.csi` | hierarchical bins plus 16 kb linear windows | one alignment | `chr1:1000-2000` |
| CRAM | `.crai` | container and slice directory | one slice | region or coordinate |
| VCF, BCF | `.tbi` or `.csi` | bins plus linear windows over BGZF blocks | one variant record | position range, gene span |
| BED, GFF, GTF | `.tbi` or a native index | bins, or a model-aware feature index | one feature | region, feature ID [2] |
| GAF (pangenome) | tabix extension in HTSlib | node-ID sorted paths over BGZF | one path | subgraph overlap [5] |
| BigWig, BigBed | internal R-tree | multi-resolution R-tree over intervals | one interval block | current browser view [6] |
| GWAS summary statistics | STABIX index | statistic-aware blocks | one statistic block | p-value range, gene [3] |

The column that surprises newcomers is the third. There is no universal granularity. A `.fai` can land on a single base because FASTA is line-oriented and predictable. A `.bai` can land on a single alignment because the binning scheme together with the linear index bounds the scan to a narrow window. An R-tree lands on a block of intervals at whatever resolution the current zoom level needs [6].

## How an Index Is Built, Step by Step

The build process is mechanical, and understanding it explains almost every index failure you will encounter.

1. **Sort the records.** Every coordinate index assumes a defined order. BAM must be coordinate sorted with `samtools sort`. VCF and BED must be sorted by chromosome and position. GAF paths are sorted by the IDs of the nodes they traverse before they can be indexed [5]. An unsorted file cannot be indexed correctly because the offsets would not be monotonic.

2. **Fix the coordinate convention.** The index records positions using the convention of the format. SAM, BAM, and VCF are 1-based. BED is 0-based, half-open. GFF is 1-based, inclusive. The `.fai` arithmetic is 0-based inside the file. Mixing conventions between a query and an index is the single most common source of one-position-off results.

3. **Compress into independent blocks.** The data stream is written as BGZF blocks, or as CRAM containers, or into the leaf nodes of an R-tree. Each block boundary becomes a potential seek target.

4. **Assign each record to a bin.** The classic BAI scheme is a hierarchy of nested genomic intervals. The coarsest bin covers 512 Mb, and each level below divides the space into 8 sub-bins, descending through levels of roughly 64 Mb, 8 Mb, 1 Mb, 128 kb, and 16 kb. A record is placed in the smallest bin that fully contains it. A long alignment that spans more than 16 kb lands in a coarser bin, which is why very long reads and structural variants still get found.

5. **Build the linear index.** A second array holds one entry per 16 kb window across the chromosome, storing the smallest virtual offset of any record that overlaps that window. This lets a reader skip forward in one jump to the start of a query window and only then scan the bins.

6. **Write the header.** The `.tbi` and `.bai` begin with a magic string, the format version, the binning depth, the list of reference sequences with their lengths, and the per-reference bin and linear-index blocks. The `.fai` is simpler, with five tab-separated columns per record: sequence name, sequence length, offset of the first base, bases per line, and bytes per line.

7. **Validate.** A correct build ends with a check that the index's recorded file size matches the data file's size and that reference lengths agree with the sequence dictionary. A mismatch should stop the pipeline.

For BAM the resulting structure supports a query in three moves. First, compute all bins that overlap the requested interval. Second, use the linear index for the interval's start window to get a minimum virtual offset and discard bin entries below it. Third, seek to the smallest surviving offset and scan forward, stopping when records pass the interval's end. The scan is bounded by the number of records in the region plus a small constant, not by the size of the file.

### The `.fai` arithmetic in concrete terms

FASTA indexing has no bins at all, only arithmetic. Suppose a record named `chr1` has its header line `>chr1` plus a newline occupying bytes 0 through 5, so the first base sits at offset 6. Sequence lines are 60 bases wide, and each line ends with one newline byte, so each full line consumes 61 bytes. The `.fai` line would read `chr1`, the sequence length, `6`, `60`, and `61`.

To find 1-based base position 1,000,001, convert to a 0-based in-sequence offset of 1,000,000, then compute:

- line number = 1,000,000 div 60 = 16,666
- byte within line = 1,000,000 mod 60 = 40
- file offset = 6 + (16,666 × 61) + 40 = 1,016,672

Two edge cases break this arithmetic if handled carelessly. The final line of a sequence is usually shorter than 60 bases, so a reader must clamp the byte count to the last valid base rather than trusting the line-length product. And a FASTA file with Windows line endings has 62 bytes per line, which is why the `.fai` stores bytes per line separately instead of assuming bases plus one. `samtools faidx` regenerates the `.fai` from the observed file, so the safest repair for a suspicious index is to delete it and rebuild.

## Index Formats in Detail

### BAM, BAI, and CSI

`.bai` is the classic BAM index, limited to reference sequences shorter than 512 Mb, which is why it works for human chromosomes but not for some plant and amphibian genomes. `.csi` is the configurable successor. It uses the same binning concept with a user-selectable depth and minimum shift, so it can address arbitrarily long references. Both store virtual offsets into the BGZF stream. Both are invalidated by any change to the data file, including recompression, filtering, or merging, because every stored offset is tied to the exact byte layout that existed at build time.

### VCF, BCF, and tabix

A tabix index requires three things of the data file: it must be BGZF compressed, it must be position sorted, and it must be tab-delimited with identifiable sequence, start, and optional end columns. Presets tell tabix how to parse each format, for example `-p vcf` or `-p bed`. The index records both bins and a 16 kb linear array, mirroring BAI. A compressed VCF that lacks a `.tbi` can still be read from beginning to end but cannot be queried by region with standard tools. That constraint is severe enough that a JavaScript module was built to work around it, fetching partial content with HTTP byte-range requests, decompressing irregularly positioned chunks on the fly, and running a binary search over chromosome-position ranges entirely inside the browser [4].

### Annotation formats: GFFx and GAF

Annotation files are the hardest case for indexing because they are hierarchical. A gene has transcripts, a transcript has exons, and a query for a gene ID should return the whole subtree rather than a flat list of lines. GFFx addresses this with a compact, model-aware index and memory-mapped input and output, reporting 10 to 80 times faster ID-based extraction, 20 to 60 times faster region retrieval, and 7 to 14 times faster coverage profiling than existing tools, with a small index footprint [2]. Pangenome annotations present a different problem, because features are paths through a graph rather than intervals on a line. Extensions to vg and HTSlib sort GAF paths by the IDs of the nodes they traverse, compress them with BGZIP, and index them with tabix, allowing fast extraction of annotations overlapping a subgraph. The plain-text GAF form proved twice as fast to sort and half as large on disk as the binary GAM alternative [5].

### Display tracks: BigWig and BigBed

Genome browsers have a different access pattern. A viewport shows a few hundred kilobases at one of several zoom levels, and the client is often far from the server. BigWig and BigBed solve this with compressed binary files that store data at multiple resolutions and index the intervals with an R-tree. Only the blocks needed to support the current view are transmitted, which is what makes fast remote display of large distributed datasets possible [6]. The multi-resolution design is the key idea: a zoomed-out view reads precomputed summaries rather than millions of individual data points.

### Statistic-aware and content-aware indices

Standard coordinate indices answer "what is at this position." They cannot answer "which variants have a p-value below 5 × 10⁻⁸" without a full scan, because that value is not part of the sort key. STABIX addresses this for GWAS summary statistics by introducing summary-statistic-based queries alongside conventional position queries. On 10 PanUKBB GWAS files it produced smaller compressed data and indices than bgzip plus Tabix for every file, with the bgzip and `.tbi` files averaging 1.2 times the size of the STABIX files, and it achieved per-gene decompression averaging 7 times faster than Tabix, beating Tabix for over 99% of nearly 20,000 genes [3].

Content-aware indexing appears in the compression literature too. One approach indexes a dictionary of significant k-mers, drawn from SNP databases and multiple genomes, in linear space and uses it to improve quality-value compression while preserving the information needed for SNP calling [7]. The index serves compression rather than retrieval, but the design trade-off is identical: spend a little space to avoid a full scan.

## FASTQ vs FASTA: Two Different Random Access Problems

FASTA and FASTQ are both plain text, and they are often confused because both begin with a `>` header in some tools and both store sequence. The difference is structural and it changes what indexing can do.

FASTA stores sequence only. A record is a header line followed by any number of wrapped sequence lines. Because the wrapping is regular, a `.fai` reduces arbitrary position lookup to the arithmetic shown above. FASTA is a coordinate-addressable format by construction. It is the right container for reference genomes, protein sets, and any sequence collection that will be queried by position. Its weakness is that it carries no per-base confidence information.

FASTQ stores four lines per read: an `@` header, the sequence, a `+` separator, and a quality string of exactly the same length as the sequence. Read lengths vary, quality strings differ in content and often in compressibility, and there is no wrapping convention to exploit. Locating read number 40,000,000 requires counting the preceding 40,000,000 records unless something records the offsets. Worse, the quality strings hold most of the entropy in the file, so they are the hardest part to compress and the part most likely to defeat naive block indexing.

Several strategies attack this. LCQS compresses quality scores losslessly with random-access decompression, and it was explicitly designed against the two failure modes of earlier tools, namely fragile output and slow compression, along with index structures that were fine-grained enough to slow compression or large enough to be impractical [8]. Reordering is another strategy. SCALCE reorganizes reads using locally consistent parsing so that similar reads sit near each other, which improves both compression speed and compression ratio and also enables random access to any read plus indexing for similarity search [9]. Read assembly before compression is a third. minicom uses large k-minimizers to index reads, groups reads sharing a minimizer into subgroups, builds a contig per subgroup, and then merges contigs using (w, k)-minimizer-indexed suffix-prefix overlaps [10]. In each case the index is doing double duty: it is both a compression aid and an access structure.

The practical consequence for workflow design is simple. Query FASTA or BAM by coordinate whenever you can. Treat FASTQ as a stream that is processed once, or as a dataset that must be reordered and indexed before any per-read retrieval is realistic.

## Random Access in Practice: Commands and Checks

The commands below are the standard interface for the formats described above. Every one of them assumes the index already exists or builds it on the spot.

Building indices:

```
samtools faidx reference.fa            # writes reference.fa.fai
samtools index aligned.sorted.bam      # writes aligned.sorted.bam.bai
samtools index -c aligned.sorted.bam    # writes a CSI index instead
bgzip -c variants.vcf > variants.vcf.gz
tabix -p vcf variants.vcf.gz            # writes variants.vcf.gz.tbi
```

Querying by region:

```
samtools faidx reference.fa chr1:1000001-1001000
samtools view aligned.sorted.bam chr7:117199644-117200000
samtools view -c aligned.sorted.bam chr7:117199644-117200000
tabix variants.vcf.gz chr7:117199644-117200000
tabix -l variants.vcf.gz                # list sequence names in the index
```

Inspecting the index and the data:

```
samtools idxstats aligned.sorted.bam    # per-reference mapped and unmapped counts
samtools quickcheck aligned.sorted.bam  # detects truncated or missing EOF blocks
bgzip -t variants.vcf.gz                # verifies BGZF integrity
```

Reading the `.fai` directly is instructive. `head -3 reference.fa.fai` prints the five columns discussed earlier, and you can confirm the offset yourself by seeking to it and checking that the first character is the expected base.

Remote access works when the server supports HTTP byte-range requests. Tools built on HTSlib can fetch a BAM, CRAM, or VCF region over HTTP by requesting only the byte ranges that the index points to. The same principle powers BigWig and BigBed display in the [UCSC Genome Browser](/knowledge/bioinformatics/ucsc-genome-browser-beginner-tutorial-and-tips), where the browser requests just the blocks needed for the current window [6]. The in-browser VCF approach extends this to files that were never indexed at all, at the cost of a binary search instead of a direct lookup [4].

## How Indexing Is Tested and Observed

A freshly built index should pass four checks before you trust it in a pipeline.

**Count reconciliation.** The sum of mapped and unmapped counts from `samtools idxstats` should equal the total read count from `samtools view -c`. A mismatch means the index was built on a different version of the file.

**Boundary probes.** Query an interval that straddles a 16 kb linear-index boundary, for example positions 16,300 to 16,500. Correct indices return records that begin before the boundary and overlap the window. Off-by-one errors and missing records usually show up here first.

**Start and end probes.** Query the first and last 200 bases of a chromosome. An index built against a different reference length will return records that do not belong or will silently drop records at the end.

**Timing comparison.** Time a region query and a whole-file count on the same machine. The region query should complete in a time that depends on the number of returned records, not on the file size. If they scale together, the tool is falling back to a scan, often because the index is missing or unrecognized.

Two further observational habits pay off. Compare modification times of the data file and its index, and rebuild whenever the data file is newer. Record the sorting order in your pipeline metadata, because a coordinate index on an unsorted file can be produced without error while returning wrong results for some queries.

## Interpreting Index Behavior Correctly

Random access genomic data indexing interpretation comes down to reading three signals: query latency, index size, and record completeness.

Query latency for a properly indexed coordinate lookup should be nearly flat as the file grows and roughly linear in the number of records returned. A query returning a few thousand alignments should take milliseconds on local disk whether the BAM is 5 GB or 50 GB. When latency grows with file size, the index is absent, stale, or being ignored.

Index size scales with the genome span covered and with record density, not with total file size alone. A BAM of short reads at high depth and a BAM of the same span at low depth have similar index sizes because the same bins and windows are populated. An annotation index that is unexpectedly large usually means the underlying feature model is being indexed at excessive granularity [2]. A tabix index that is unexpectedly small usually means a chromosome naming mismatch left most references unindexed.

Record completeness is the third signal and the subtlest. Indexed queries return the records the index points to, so errors in the index become silent omissions rather than visible failures. The classic cases are a stale index after filtering, a reference dictionary in which `chr1` and `1` are treated as different sequences, and a query expressed in a different coordinate convention from the index. None of these produces an error message. All of them produce a plausible-looking but incomplete result set. That is why count reconciliation and boundary probes belong in automated tests, not in manual troubleshooting.

Compression ratios interact with retrieval design. A whole-collection compressor can reach far smaller sizes than per-file compression, with one reported result of about 9,500-fold compression across 1,092 human diploid genomes, roughly 4 times better than other compressors at the time, processing at about 200 MB/s and shrinking 6.7 TB to about 700 MB [1]. Such archives are excellent for storage and distribution but they change the access model, since a query must go through the collection-level structure rather than a per-file byte offset. Choose an index strategy that matches how the archive will be queried, not just how it will be stored.

## Comparative and Clinical Relevance

For clinical variant interpretation, the query pattern is a short list of loci. A reporting pipeline takes a VCF or BAM and asks about a few hundred positions spanning a handful of genes. Without indexing, each question is a full pass. With a tabix index over the VCF and a BAI over the BAM, the same questions become a few hundred seeks. The saved time is not the main benefit. The main benefit is that the analysis can be rerun interactively when a curator wants to inspect a call, which is what makes reanalysis of negative cases practical.

At biobank scale the problem is summary statistics rather than reads. Thousands of traits are published as GWAS files, and position-based queries alone cannot answer questions phrased in terms of significance. STABIX closes that gap by making the summary statistic itself part of the access structure, while also beating bgzip plus Tabix on both compressed size and per-gene decompression speed across the 10 PanUKBB files tested [3]. The pattern generalizes: when users ask questions about a value, index the value.

For genome browsers the constraint is bandwidth. BigWig and BigBed exist because transmitting whole files to a browser is impossible, and the multi-resolution R-tree lets the client fetch only the data that the current view requires [6]. For pangenome projects the constraint is that coordinates no longer form a line. Sorting and indexing GAF paths by node ID, then querying by subgraph, gives the same fast overlap retrieval that linear formats enjoy, with the added benefit of a human-readable text format [5]. For annotation-heavy pipelines, a model-aware Rust index with memory-mapped I/O delivers large speedups over generic text tools while keeping memory low [2].

There are also cases where the right answer is to avoid indexing entirely. In DNA-based archival storage, one biomedical image system uses an error-correcting encoding scheme that removes the need for an index, trading retrieval flexibility for storage density and decode speed [11]. That is a reminder that an index is a design choice with real costs, not a universal requirement.

## Common Mistakes and Limitations

**Indexing an unsorted file.** Sorting is a prerequisite, not a recommendation. A coordinate index built on an unsorted BAM may be produced without complaint and will return wrong subsets for many queries.

**Editing the data file after indexing.** Any rewrite changes byte offsets. Always rebuild the index after `samtools sort`, `samtools merge`, filtering, or recompression.

**Assuming `.gz` means queryable.** A plain gzip file has no block structure and no index. Only BGZF-compressed files can carry a `.tbi` or be addressed by virtual offset.

**Mixing coordinate conventions.** BED is 0-based and half-open. VCF and GFF are 1-based. A BED interval of `chr1 999 2000` and a VCF query of `chr1:1000-2000` describe the same window only if you convert carefully.

**Chromosome naming mismatches.** `chr1` and `1` are distinct keys. An index containing one naming scheme will return nothing for queries using the other. Standardize contig names across reference, alignment, and annotation before indexing.

**Ignoring reference-length limits.** Classic BAI cannot address references longer than 512 Mb. Use CSI for large plant or amphibian genomes.

**Treating index size as free.** Fine-grained indices improve seek precision and cost disk and build time. Fine-grained quality-score indices were specifically criticized for slowing compression and inflating index files [8]. Measure both sides.

**Assuming return order equals file order for merged queries.** A region query returns records in file order within that region, which is coordinate order only if the file was coordinate sorted to begin with.

**Expecting FASTQ to behave like FASTA.** There is no standard FASTQ index. Per-read retrieval requires reordering or a tool-specific structure [9][10].

A final limitation is inherent to the model. An index tells you where records are, not whether they are correct. It cannot detect a mislabeled sample, a wrong reference build used during alignment, or a variant caller error. Those are questions for validation steps upstream, and no amount of seek efficiency substitutes for them. For any individual clinical case, a qualified professional must review the evidence.

## Quick Review

- Random access means seeking directly to a region. An index is the side file that maps a coordinate, identifier, or statistic to a byte position.
- Plain gzip cannot be seeked. BGZF block compression makes every 64 KB block independently inflatable, and virtual offsets encode block address plus in-block position.
- `.fai` handles FASTA with pure arithmetic from sequence length, offset, bases per line, and bytes per line.
- `.bai` and `.csi` combine hierarchical bins with a 16 kb linear index. `.tbi` applies the same idea to BGZF-compressed text such as VCF and BED.
- BigWig and BigBed use multi-resolution R-trees so browsers transmit only the blocks needed for the current view.
- FASTQ has no standard index because variable-length records and high-entropy quality strings defeat simple offset arithmetic.
- A stale or mismatched index fails silently. Reconcile counts, probe bin boundaries, and rebuild after every data rewrite.

## Frequently Asked Questions

### What does random access to genomic data mean?

Random access means retrieving a specific region or record directly, without reading the bytes before it. It requires an index that records where each region's records start in the file.

### Is a .bai index the same as a .tbi index?

No. Both use hierarchical bins and a linear index, but `.bai` stores virtual offsets into a BAM binary stream while `.tbi` indexes BGZF-compressed tab-delimited text such as VCF or BED.

### Why does a region query fail with "index not found"?

The tool could not locate the expected index file next to the data file. Build it with `samtools index` for BAM or `tabix -p vcf` for a compressed VCF, and confirm the file name matches what the tool expects.

### Can a plain gzip file be queried by region?

No. A standard gzip stream must be inflated from the start, so there is no valid place to seek. Recompress with `bgzip` and build the appropriate tabix index instead.

### What is the difference between FASTQ and FASTA for indexing?

FASTA supports reliable coordinate lookup because sequence lines are regularly wrapped and a `.fai` can compute any base position by arithmetic. FASTQ has variable-length four-line records and no standard index, so per-read access needs reordering or a specialized tool.

### Can a VCF be queried without an index?

Only by reading the entire file. Region queries with tools like tabix require a `.tbi` or `.csi`, although specialized approaches can fall back to byte-range requests and binary search over unindexed files.

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "FAQPage",
  "mainEntity": [
    {
      "@type": "Question",
      "name": "What does random access to genomic data mean?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Random access means retrieving a specific region or record directly, without reading the bytes before it. It requires an index that records where each region's records start in the file."
      }
    },
    {
      "@type": "Question",
      "name": "Is a .bai index the same as a .tbi index?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "No. Both use hierarchical bins and a linear index, but .bai stores virtual offsets into a BAM binary stream while .tbi indexes BGZF-compressed tab-delimited text such as VCF or BED."
      }
    },
    {
      "@type": "Question",
      "name": "Why does a region query fail with index not found?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "The tool could not locate the expected index file next to the data file. Build it with samtools index for BAM or tabix -p vcf for a compressed VCF, and confirm the file name matches what the tool expects."
      }
    },
    {
      "@type": "Question",
      "name": "Can a plain gzip file be queried by region?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "No. A standard gzip stream must be inflated from the start, so there is no valid place to seek. Recompress with bgzip and build the appropriate tabix index instead."
      }
    },
    {
      "@type": "Question",
      "name": "What is the difference between FASTQ and FASTA for indexing?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "FASTA supports reliable coordinate lookup because sequence lines are regularly wrapped and a .fai can compute any base position by arithmetic. FASTQ has variable-length four-line records and no standard index, so per-read access needs reordering or a specialized tool."
      }
    },
    {
      "@type": "Question",
      "name": "Can a VCF be queried without an index?",
      "acceptedAnswer": {
        "@type": "Answer",
        "text": "Only by reading the entire file. Region queries with tools like tabix require a .tbi or .csi, although specialized approaches can fall back to byte-range requests and binary search over unindexed files."
      }
    }
  ]
}
</script>

## Sources

1. [GDC 2: Compression of large collections of genomes.](https://pubmed.ncbi.nlm.nih.gov/26108279/)
2. [GFFx: A Rust-based suite of utilities for ultra-fast genomic feature extraction.](https://pubmed.ncbi.nlm.nih.gov/41129325/)
3. [STABIX: summary-statistic-based GWAS indexing and compression.](https://pubmed.ncbi.nlm.nih.gov/40315153/)
4. [FAIR privacy-preserving operation of large genomic variant calling format (VCF) data without download or installation.](https://pubmed.ncbi.nlm.nih.gov/38827109/)
5. [Efficient indexing and querying of annotations in a pangenome graph.](https://pubmed.ncbi.nlm.nih.gov/39464141/)
6. [BigWig and BigBed: enabling browsing of large distributed datasets.](https://pubmed.ncbi.nlm.nih.gov/20639541/)
7. [Indexing k-mers in linear space for quality value compression.](https://pubmed.ncbi.nlm.nih.gov/31856669/)
8. [LCQS: an efficient lossless compression tool of quality scores with random access functionality.](https://pubmed.ncbi.nlm.nih.gov/32183707/)
9. [SCALCE: boosting sequence compression algorithms using locally consistent encoding.](https://pubmed.ncbi.nlm.nih.gov/23047557/)
10. [Index suffix-prefix overlaps by (w, k)-minimizer to generate long contigs for reads compression.](https://pubmed.ncbi.nlm.nih.gov/30407482/)
11. [DNA data storage for biomedical images using HELIX.](https://pubmed.ncbi.nlm.nih.gov/40360759/)