All Docs
FeaturesNurtureHubUpdated March 21, 2026

Inngest Background Job Foundation

Inngest Background Job Foundation

Version introduced: v1.0.40

NurtureHub's background job system is built on Inngest, a durable workflow engine that handles all AI agent execution, CRM synchronisation, intent scoring, and alert delivery. This page documents the foundational conventions, schemas, and policies that every background process on the platform follows.


Overview

Every AI-powered action in NurtureHub — generating a nurture sequence, syncing a contact update to a CRM, scoring engagement intent, or firing a hot lead alert — runs as a durable Inngest function. The v1.0.40 release formalises the contract that all of these functions share:

  • A standardised event naming convention
  • Zod-validated payload schemas for every event type
  • Per-tenant concurrency limits for fair resource allocation
  • Retry policies with exponential backoff for resilience
  • Shared step utilities consumed by all agent functions

Event Naming Convention

All Inngest events emitted by NurtureHub follow a consistent domain/action naming pattern. This makes event routing, logging, and debugging predictable across the entire platform.

<domain>/<action>

Examples:

Event NameDescription
nurture/sequence.generateTrigger AI generation of a three-email nurture sequence
contact/category.assignedA contact has been assigned to one of the twelve categories
crm/sync.pushPush a contact or sequence update to the connected CRM
lead/intent.scoreRe-score a contact's intent based on new engagement data
alert/hot-lead.fireDispatch a hot lead alert to the assigned agent

All event names use lowercase with dot-separated action segments. New events added to the platform must follow this convention.


Payload Schemas & Zod Validation

Every event payload is defined as a Zod schema and validated at the point of emission. This ensures:

  • Malformed payloads are rejected before entering the job queue.
  • TypeScript types are inferred directly from schemas, keeping event producers and consumers in sync.
  • Runtime validation errors surface immediately, rather than causing silent failures deep inside an agent function.

Example payload schema (illustrative):

import { z } from 'zod';

export const NurtureSequenceGeneratePayload = z.object({
  tenantId: z.string().uuid(),
  contactId: z.string().uuid(),
  category: z.enum([
    'seller',
    'landlord',
    'buy-to-let-investor',
    'active-tenant',
    // ... all twelve categories
  ]),
  brandVoice: z.string().min(1),
  triggeredAt: z.string().datetime(),
});

export type NurtureSequenceGeneratePayload = z.infer<
  typeof NurtureSequenceGeneratePayload
>;

All agent functions receive a validated, fully-typed payload — no defensive casting required inside function bodies.


Concurrency Limits Per Tenant

To ensure fair resource usage across all agency accounts, each Inngest function enforces a per-tenant concurrency limit. This prevents a single tenant from saturating the background job queue during high-volume periods (e.g. a bulk import of new contacts).

Concurrency is keyed on tenantId so that each agency's jobs run independently of one another. Queued jobs beyond the limit are held and executed in order as capacity becomes available — no jobs are dropped.

// Concurrency is configured at function registration
{
  concurrency: {
    limit: <N>,
    key: 'event.data.tenantId',
  }
}

The specific concurrency limit per tenant is set at the infrastructure level and may be adjusted as the platform scales.


Retry Policy — Exponential Backoff

All Inngest functions on the platform use a shared retry policy with exponential backoff. This provides resilience against transient failures such as:

  • Temporary AI API rate limits or timeouts
  • CRM webhook delivery failures
  • Database contention under load

Policy summary:

PropertyBehaviour
Max attemptsConfigured per function category
Backoff strategyExponential (doubles on each retry)
Retry scopePer Inngest step, not per entire function run
Failure handlingAfter max retries, the run is marked as failed and logged

Because Inngest retries at the step level, successfully completed steps within a function are not re-executed — only the failing step is retried. This makes long-running agent pipelines safe to retry without duplicating side effects.


Shared Step Utilities

A library of shared step utilities is provided for all agent functions to import. These utilities standardise how common operations are performed across the job pipeline.

Typical utilities include:

  • Tenant context resolution — look up agency settings, brand voice, and CRM credentials from a tenantId.
  • CRM client factory — return the correct CRM adapter (agentOS, Reapit, Alto, Street, Loop) based on the tenant's configured integration.
  • AI prompt construction — build structured prompts with the agency's brand voice and contact category injected.
  • Event emission helpers — emit follow-on events (e.g. after generation completes, emit a crm/sync.push event) with type-safe, pre-validated payloads.
  • Logging and tracing — attach structured metadata to Inngest step logs for observability.

Using the shared utilities ensures consistency and reduces the chance of per-agent implementation drift.


Architecture Diagram

┌─────────────────────────────────────────────────┐
│                  NurtureHub App                 │
│                                                 │
│  Contact assigned to category                   │
│        │                                        │
│        ▼                                        │
│  Emit validated Inngest event                   │
│  (Zod schema enforced at emission)              │
│        │                                        │
└────────┼────────────────────────────────────────┘
         │
         ▼
┌─────────────────────────────────────────────────┐
│                  Inngest Platform               │
│                                                 │
│  ┌──────────────────────────────────────────┐  │
│  │  Function: nurture/sequence.generate     │  │
│  │  - Concurrency limit (per tenantId)      │  │
│  │  - Retry policy (exponential backoff)    │  │
│  │  - Shared step utilities                 │  │
│  │    ├── step: resolve tenant context      │  │
│  │    ├── step: build AI prompt             │  │
│  │    ├── step: call AI API                 │  │
│  │    ├── step: store sequence              │  │
│  │    └── step: emit crm/sync.push          │  │
│  └──────────────────────────────────────────┘  │
│                                                 │
└─────────────────────────────────────────────────┘

Related