Run it locally under Aspire
You have built the whole ERP sync: a file-watch import job, a queue, and a cron schedule, plus an
understanding of polyglot transform tasks. This final chapter runs all of it together — workers,
triggers, queue, and cron processors — on one machine under aspire start, and shows you how to read
the running system from the dashboard. It is the local orchestration story: one command,
one observable stack, throwaway infrastructure.
What you will build
By the end of this chapter you will bring the full my-erp/ resource graph up with a single
aspire start — Postgres, Redis, the workers API + processor, and the triggers API + processor (which
runs your file-watch and cron triggers) — initialize the database through the running AppHost, and
read the live import pipeline in the Aspire dashboard: resources, console logs, and the traces that
stitch a file drop to its job execution.
Before you begin
You need the complete my-erp/ workspace from Chapter 4:
the workers and triggers plugins, the import-products job, the product-import-trigger file watch,
and the daily-resync-schedule cron. Docker must be running so Aspire can provision Postgres and
Redis. Confirm the AppHost was scaffolded (it is a TypeScript/Node program, not C#):
ls aspire/apphost.mts aspire/aspire.config.json
Expected: both files exist. netscript init generated them in Chapter 1; you never hand-write them.
Step 1 — Understand the graph you are about to run
The resource graph is derived from your installed plugins at boot via composeAppHost — add a
plugin and its API plus background processor appear; remove it and they vanish, no edit to
apphost.mts. With workers and triggers installed, a single aspire start stands up this graph:
| Name | Type | Description |
|---|---|---|
aspire (dashboard) |
https://localhost:18888 / http://localhost:18889 |
Live resource list, console logs, structured logs and traces. A login token is printed on start. |
OTLP collector |
http://localhost:4318 |
OpenTelemetry endpoint the dashboard runs; framework spans and structured logs land here automatically. |
postgres |
Container |
Throwaway Docker Postgres. The database netscript db commands target — reachable only while Aspire is up. |
redis |
Container (cache) |
Redis cache — the default --cache-backend; Redis-compatible. Backs the KV/queue workloads — this is what auto-discovery resolves the queue to once it is up. |
workers API + processor |
:8091 (PLUGIN_API range) + executable |
The :8091 API enqueues; a separate background processor drains the queue and runs your import job. |
triggers API + processor |
:8093 (PLUGIN_API range) + executable |
The :8093 API plus the processor that runs your file-watch and cron triggers. |
Step 2 — Restore and run
The AppHost runs on its own isolated Node runtime inside aspire/ so its dependencies never leak
into your Deno workspace. Restore once per machine, then run — both from inside aspire/:
cd aspire
aspire restore # one-time SDK restore (and after an SDK bump)
aspire start # boots the whole graph; prints the dashboard URL + a login token
aspire start brings up infrastructure first, then the plugin APIs and background processors, with
cross-references resolved into injected environment variables. Leave it running.
Step 3 — Initialize the database through the running AppHost
With Aspire up, Postgres is live and the netscript db commands can reach it. Run them from the
workspace root in a second terminal (leave aspire start going in the first):
netscript db init --name init # create + apply the first migration
netscript db generate # generate the Prisma client
netscript db seed # optional: seed development data
These talk to the Postgres container Aspire provisioned. Run them with no Aspire up and they fail — there is no Postgres for them to reach.
Step 4 — Watch the pipeline run end to end
With the full stack up, exercise the pipeline you built and read it from the dashboard. Drop a file:
cat > .data/incoming/products_live.csv <<'CSV'
name,sku,price
Anvil,ANV-9,49.99
CSV
mv .data/incoming/products_live.csv .data/incoming/products/products_live.csv
Then open https://localhost:18888, paste the login token aspire start printed, and use the three
dashboard surfaces:
| Name | Type | Description |
|---|---|---|
Resources |
tab |
Every container and executable with status and the port it bound. Confirm workers, triggers, postgres, and redis are all green. |
Console logs |
tab |
stdout/stderr per resource. Open the workers processor to read your import job's log lines; the triggers processor shows the file-watch event. |
Structured logs + Traces |
tab |
Spans correlated by traceparent. The framework instruments job dispatch and execution automatically, so a file drop → job run trace appears with no extra wiring. |
Because Aspire starts each resource with an OTLP endpoint pointed at http://localhost:4318,
framework-level spans (job dispatch, job execution, scheduler runs) surface in the Traces view on
their own.
Verify your progress
Confirm the whole graph is healthy and the pipeline ran:
# Both plugin APIs answer.
curl http://localhost:8091/health
curl http://localhost:8093/health
# The dropped file produced an import execution.
curl 'http://localhost:8091/api/v1/workers/executions?limit=10'
Expected: both health checks return healthy JSON, and the executions feed shows a completed
import-products run for products_live.csv.
- [ ]
aspire startis up; the dashboard listspostgres,redis, workers, and triggers all green. - [ ]
netscript db init/generatesucceeded against the Aspire Postgres. - [ ]
curl :8091/healthandcurl :8093/healthboth return healthy. - [ ] A file drop produced an
import-productsexecution and a dispatch/execution trace in the dashboard.
What you built
You ran the complete ERP sync — workers, triggers, queue, and cron — on one machine under a single
aspire start, initialized the database through the running AppHost, and watched a file drop flow into
a durable job execution with its trace in the dashboard. You now have an end-to-end durable
background-processing backend, and you know exactly where the local story ends and a production
deployment begins.
Where to go next
You have finished the ERP Sync track. From here, branch into task-oriented and reference docs:
- Ship it remotely → Deploy — the production companion to this local run:
deployable units, managed backing services, and the
--no-aspirepath. - Run a polyglot task for real → Run a polyglot task — turn Chapter 3's documented capability into a running Python or shell step.
- Tune throughput → Choose a queue provider and Tune the worker runtime.
- Understand the orchestrator → Orchestration with Aspire and the full How-to guides.