How to serve a RefgetStore concurrently
Serve GA4GH sequence collection endpoints from a local RefgetStore, with the store shared across request threads instead of locked per request. No database is required.
1. Open the store and preload
Section titled “1. Open the store and preload”Open the store with the mutable RefgetStore type, then load everything the service will need. ReadonlyRefgetStore cannot lazy-load, so anything not loaded here will be unavailable at request time.
from refget.store import RefgetStore
store = RefgetStore.open_local("/data/refget-store")store.set_quiet(True)store.load_all_collections()load_all_collections() is the requirement for level 2 retrieval, comparison, and attribute lookup. Level 1 digests and collection listing work without it, but load it anyway unless startup time is critical: it reads metadata only, not sequence bytes.
To confirm what you have:
info = store.stats()print(info["n_collections"], "collections;", info["n_collections_loaded"], "loaded")2. Convert to a readonly store
Section titled “2. Convert to a readonly store”readonly = store.into_readonly()After this call, store is empty and must not be used. Use readonly from here on.
3. Wire the store into a FastAPI app
Section titled “3. Wire the store into a FastAPI app”setup_backend wraps whatever store you hand it in a RefgetStoreBackend and attaches it to app.state.backend. It does not load or convert anything, so the store you pass must already be in its final state.
from contextlib import asynccontextmanager
from fastapi import FastAPIfrom refget.router import create_refget_router, setup_backendfrom refget.store import RefgetStore
@asynccontextmanagerasync def lifespan(app: FastAPI): store = RefgetStore.open_local("/data/refget-store") store.set_quiet(True) store.load_all_collections() setup_backend(app, store=store.into_readonly()) yield
app = FastAPI(lifespan=lifespan)app.include_router( create_refget_router(collections=True, sequences=False), prefix="/seqcol",)Doing the load inside lifespan keeps startup cost in one place and guarantees the backend is ready before the first request is accepted.
4. Run with a thread pool
Section titled “4. Run with a thread pool”FastAPI dispatches synchronous route handlers to a thread pool, so a single process serves many requests in parallel against the one shared store. Run one worker process per machine and let the threads do the concurrency; each additional process would hold its own full copy of the store in memory.
uvicorn myapp:app --host 0.0.0.0 --port 8100 --workers 15. Verify
Section titled “5. Verify”curl -s http://localhost:8100/seqcol/list/collection | headcurl -s http://localhost:8100/seqcol/collection/<digest>?level=2Success looks like: collection listing returns a results array and a pagination object, level 2 retrieval returns names, lengths, and sequences arrays, and response times stay flat as you increase concurrent clients. If a collection request returns an error mentioning that the collection is not loaded, step 1 was skipped or incomplete.
Serving sequence endpoints
Section titled “Serving sequence endpoints”Sequence and substring endpoints need more preloading, and the requirement differs by store location.
For a local store, sequence bytes are read directly from .seq files even for records that were never promoted, so load_all_collections() is sufficient for get_substring and get_substrings. Add load_all_sequences() only if you want every sequence resident in RAM.
For a remote-backed store, the sequence index is deferred until first access and the readonly store cannot fetch it. Call load_all_sequences() before converting, which downloads every sequence into the local cache. In practice, mirror the store locally rather than serving sequence bytes straight from a remote source.
Choosing this over a database backend
Section titled “Choosing this over a database backend”RefgetStoreBackend covers the core seqcol operations: retrieval at both levels, comparison, attribute search, and listing. Pangenome endpoints, DRS endpoints, and the database-only administrative routes require RefgetDBAgent and PostgreSQL. See adding a FastAPI router for the database-backed setup.