Skip to main content

Embedded Backend Example

The embedded backend example runs one process with two frontends:

  • REST endpoints for predefined citation-network pipelines.
  • Arrow Flight SQL for ad-hoc SQL, metadata, prepared statements, and cancel.

Both frontends share one NexusGpuBackend and one base SessionContext. REST requests use the backend-installed session's plan-scoped admission tickets. Flight SQL statements issue Flight tickets first and acquire GPU admission only when a native plan starts executing. Native work from both paths draws slots and memory grants from the same query-service ledger, which is exposed by GET /api/gpu.

one backend process
+----------------------------------------+
A: HTTP client ----------> example HTTP API |
| /api/pipelines, /api/gpu |
| | |
| | |
B: Flight SQL client ----> Flight SQL frontend |
| SQL, metadata, cancel |
| | |
| v |
| shared DataFusion SessionContext |
| | |
| v |
| NexusGpuBackend |
| QueryService admission ledger |
| | |
| v |
| cuDF / cuGraph on CUDA |
+------------------|---------------------+
|
v
Iceberg REST catalog
lake.citation_network tables
|
v
RustFS/S3 staged Citation Network Parquet

Use this shape when a Rust service owns product workflows but still needs an expert SQL side door for notebooks, operators, or BI tools. The demo is deliberately neutral: the pipelines are named by the capability they exercise, not by a fictional product domain.

What It Demonstrates

SurfaceWhat it proves
RESTPredefined, parameter-validated SQL and graph pipelines can return JSON rows and planning reports.
Flight SQLAd-hoc clients see the same catalog workspace and can run SQL, prepared statements, metadata calls, and cancel.
Shared backendREST and Flight native execution share one admission queue, one memory-governor ledger, and one CUDA runtime owner.
Iceberg RESTThe Citation Network demo tables are registered with Iceberg add_files, so the local catalog references existing Parquet files instead of rewriting them.

Data Prerequisite

The example uses the Citation Network demo dataset: 4,894,081 papers and 45,564,149 citation edges. Generate the Parquet files from the upstream dblp.v12.json file, then load them into the local Iceberg REST catalog with add-files mode:

python3 fixture/graph/dblp_ingest.py \
--source-json /path/to/dblp.v12.json \
--out-root fixture/graph/demo \
--overwrite

docker compose -f fixture/iceberg-local/docker-compose.yml up -d
fixture/fixture.sh iceberg rest load \
--workload citation_network \
--load-mode add-files

add-files stages the Parquet files into RustFS and Iceberg references those staged files in place. Do not delete the staging prefix while the local REST catalog metadata is live. The REST fixture metadata is ephemeral, so rerun the loader after every fresh docker compose up.

Run It

The example consumes the same server configuration contract as the Flight SQL server, plus EXAMPLE_REST_BIND. EXAMPLE_REST_BIND is the bind address for this example's own axum HTTP API (/healthz, /api/pipelines, /api/gpu). It is not the Iceberg REST catalog endpoint; the Iceberg REST catalog endpoint is NEXUS_ICEBERG_REST_URI.

EXAMPLE_REST_BIND=127.0.0.1:8080 \
NEXUS_SERVER_BIND=127.0.0.1:50051 \
NEXUS_SERVER_CUGRAPH_ENABLED=true \
DATAFUSION_CATALOG_DEFAULT_CATALOG=datafusion \
DATAFUSION_CATALOG_DEFAULT_SCHEMA=public \
NEXUS_ICEBERG_CATALOG_KIND=rest \
NEXUS_ICEBERG_CATALOG_NAME=lake \
NEXUS_ICEBERG_NAMESPACE=citation_network \
NEXUS_ICEBERG_WAREHOUSE=s3://lakehouse/warehouse \
NEXUS_ICEBERG_REST_URI=http://localhost:8181 \
NEXUS_ICEBERG_S3_ENDPOINT=http://localhost:9000 \
NEXUS_ICEBERG_S3_REGION=us-east-1 \
NEXUS_ICEBERG_S3_PATH_STYLE=true \
NEXUS_ICEBERG_S3_ACCESS_KEY_ID=nexusadmin \
NEXUS_ICEBERG_S3_SECRET_ACCESS_KEY=nexusadmin \
NEXUS_SERVER_WORKSPACE_CATALOG=datafusion \
NEXUS_SERVER_WORKSPACE_SCHEMA=public \
NEXUS_SERVER_WORKSPACE_BACKING_CATALOG=lake \
NEXUS_SERVER_WORKSPACE_BACKING_SCHEMA=citation_network \
NEXUS_SERVER_WORKSPACE_BACKING_ALIASES=papers,paper_fos,citation_edges,citation_edges_by_dst \
flock /tmp/cudf-gpu.lock \
cargo run -p nexus-examples --all-features --bin embedded_backend

Use the exact Iceberg keys shown above. NEXUS_ICEBERG_CATALOG=rest is not a server config key, and NEXUS_ICEBERG_REST_WAREHOUSE is not read by the REST catalog path. NEXUS_ICEBERG_CATALOG_KIND is required whenever Iceberg settings are present, so a missing or misspelled NEXUS_ICEBERG_CATALOG_KIND=rest now fails startup directly with its own error rather than falling through to a Glue-specific AWS_REGION complaint.

The example HTTP API frontend binds to EXAMPLE_REST_BIND. The Flight SQL frontend binds to NEXUS_SERVER_BIND. The backend connects to the Iceberg REST catalog at NEXUS_ICEBERG_REST_URI.

REST Pipelines

List the available pipelines and run one:

curl http://127.0.0.1:8080/healthz
curl http://127.0.0.1:8080/api/pipelines

curl -X POST http://127.0.0.1:8080/api/pipelines/sql_aggregate_topk \
-H 'content-type: application/json' \
-d '{"year_from":2010,"year_to":2020,"limit":10}'

The predefined pipelines are:

PipelineCapability
sql_aggregate_topkFilter, sort, and limit over papers.
sql_join_facetsJoin paper_fos to papers, then group and aggregate.
graph_pagerank_topkRun cugraph_pagerank, join vertices back to papers, and return top scores.
graph_bfs_hopsRun cugraph_bfs, join vertices back to papers, and aggregate by hop distance.

Each pipeline also exposes a plan endpoint:

curl http://127.0.0.1:8080/api/pipelines/sql_aggregate_topk/plan

The response contains the native PlanningReport JSON for the pipeline's default parameters. Treat Selected as native execution evidence; NotSupported and NotSelectedByCost retain the reason for a non-native choice. Do not depend on printed physical plans.

Ad-Hoc Flight SQL

Flight SQL clients connect to the same process at grpc://127.0.0.1:50051. They see the same unqualified workspace names as the REST pipelines.

printf '%s\n' \
"SELECT count(*) FROM papers" \
"CREATE VIEW ai_edges AS SELECT e.src, e.dst, e.weight FROM citation_edges e JOIN paper_fos f ON e.src = f.paper_id WHERE f.fos_name = 'Artificial intelligence'" \
"SELECT vertex, distance FROM cugraph_bfs('ai_edges', 2963403868, 'src', 'dst', NULL, '{\"depth_limit\":1,\"output_mode\":\"normalized\"}') ORDER BY distance, vertex LIMIT 10" |
arrow_cli --host 127.0.0.1 -P 50051 --timeout 120 --output table

Keep multi-statement experiments in one client process when they depend on session-local views.

E2E Suite

The black-box suite starts the local stack, loads the citation network with --load-mode add-files, spawns the example process, and checks catalog truth, REST pipeline results, Flight SQL graph queries, shared-ledger overload, and graceful shutdown:

crates/nexus-examples/scripts/e2e.sh

Use --skip-stack when the REST catalog and RustFS are already running, and --reload when you want the loader to drop and re-add the Iceberg tables. The suite intentionally fails fast with acquisition instructions if the citation-network Parquet files are missing.

Embedding APIs

The example is built on the same public APIs available to application code:

  • nexus_server::backend_from_server_config(&config) builds the bounded backend from the server configuration contract.
  • FlightSqlServer::builder().backend(backend.clone()) runs the built-in Flight SQL server on that backend.
  • server.session_context() returns the shared base session for other frontends.
  • build_session_context_with_backend(&config, &backend) is the lower-level session builder for REST-only or custom frontend embedders.

Injected sessions and backends are validated together. A caller-built session must carry the same backend admission source, and server config that conflicts with an injected backend is rejected instead of silently creating a second GPU authority.