---
title: Job Discovery and Runtime Registration
description: How DurableStack registers jobs in .NET and Node.js, including .NET assembly discovery and Node startup registration.
order: 32
available_in: [dotnet, nodejs]
---

# Job Discovery and Runtime Registration

## Overview

DurableStack job registration is runtime-specific.

In .NET, job types can be auto-discovered from assemblies (default starts from the host assembly).

In Node.js, jobs are registered explicitly at startup (for example, `runtime.registerJob(...)` or `runtime.registerRecurring(...)`), not discovered from assemblies.

## Common scenario

In many real-world .NET solutions, the application host and job implementations are intentionally separated across projects. Since discovery starts from the host assembly, default auto-discovery only sees job types in that assembly. When jobs are defined in another referenced assembly, explicitly registering that assembly ensures they are discovered at startup.

In Node.js, the equivalent pattern is calling one startup registration function per package/module that contains jobs.

## Register jobs from another assembly (.NET)

Use `AddDurableJobsFromAssembly` and point it to an assembly that contains your job types.

:::code-group
```csharp
services.AddDurableStack(options =>
{
    options.UsePostgres(DataSettingsManager.LoadSettings().ConnectionString);
});

services.AddDurableJobsFromAssembly(typeof(ClearCacheTask).Assembly);
```

```typescript
import { createDurableStackPostgres } from "durablestack";
import { registerBillingJobs } from "@acme/billing-jobs";

const { runtime } = await createDurableStackPostgres({
  connectionString: process.env.DATABASE_URL!
});

registerBillingJobs(runtime);
```
:::

`ClearCacheTask` is a .NET anchor type. DurableStack scans that assembly and discovers matching public job types there.

## Recommended pattern

- .NET: keep your normal `AddDurableStack(...)` registration.
- .NET: add one `AddDurableJobsFromAssembly(...)` call per external assembly that contains jobs.
- .NET: use a stable, known job type from that project as the anchor (`typeof(SomeJob).Assembly`).
- Node.js: call each jobs package/module registration function during startup.

## Multiple assemblies

If .NET jobs are split across projects, register each assembly explicitly.

:::code-group
```csharp
services.AddDurableJobsFromAssembly(typeof(BillingJobsAssemblyMarker).Assembly);
services.AddDurableJobsFromAssembly(typeof(ReportingJobsAssemblyMarker).Assembly);
```

```typescript
import { registerBillingJobs } from "@acme/billing-jobs";
import { registerReportingJobs } from "@acme/reporting-jobs";

registerBillingJobs(runtime);
registerReportingJobs(runtime);
```
:::

## Troubleshooting checklist

- .NET: confirm the jobs project is referenced by the host project.
- .NET: confirm job types are public and implement DurableStack job contracts.
- Confirm registration runs during startup before worker execution begins.
- If no jobs appear, log startup and verify your assembly or module registration path is executed.
