Skip to main content
Inngest handles background jobs in Polaris, including AI processing, GitHub import/export, and other long-running tasks.

Why Inngest?

Inngest provides critical features for Polaris:
  • Non-blocking UI - Long tasks don’t freeze the interface
  • Automatic retries - Failed jobs retry with exponential backoff
  • Job steps - Break complex jobs into resumable steps
  • Cancellation - Stop jobs mid-execution
  • Monitoring - View job status and logs in the dashboard

Setup

1

Create an Inngest account

Visit inngest.com and create a free account.
2

Install Inngest CLI

npm install -g inngest-cli
3

Start the dev server

npx inngest-cli@latest dev
This runs the Inngest dashboard at http://localhost:8288.
4

Configure the API endpoint

Inngest functions are registered at /api/inngest in your Next.js app.The endpoint is defined in src/app/api/inngest/route.ts:
import { serve } from "inngest/next";
import { inngest } from "@/inngest/client";
import * as functions from "@/inngest/functions";

export const { GET, POST, PUT } = serve({
  client: inngest,
  functions: Object.values(functions),
});

Key jobs in Polaris

GitHub import

Imports a GitHub repository into a Polaris project:
export const importGithubRepo = inngest.createFunction(
  {
    id: "import-github-repo",
    cancelOn: [
      {
        event: "projects/import.cancelled",
        match: "data.projectId",
      },
    ],
  },
  { event: "projects/import.requested" },
  async ({ event, step }) => {
    const { projectId, repoUrl, accessToken } = event.data;

    // Clone repository
    const files = await step.run("clone-repo", async () => {
      return await cloneGithubRepo(repoUrl, accessToken);
    });

    // Create folder structure
    await step.run("create-folders", async () => {
      return await createFolders(projectId, files);
    });

    // Import files
    await step.run("import-files", async () => {
      return await importFiles(projectId, files);
    });
  }
);

AI message processing

Processes AI chat messages with tools:
export const processMessage = inngest.createFunction(
  {
    id: "process-message",
    cancelOn: [
      {
        event: "messages/process.cancelled",
        match: "data.messageId",
      },
    ],
  },
  { event: "messages/process.requested" },
  async ({ event, step }) => {
    const { messageId, conversationId } = event.data;

    // Get conversation history
    const messages = await step.run("get-messages", async () => {
      return await getConversationMessages(conversationId);
    });

    // Run AI agent
    const result = await step.run("run-agent", async () => {
      return await runAgentWithTools(messages);
    });

    // Save response
    await step.run("save-response", async () => {
      return await saveMessage(conversationId, result);
    });
  }
);

GitHub export

Exports a Polaris project to GitHub:
export const exportToGithub = inngest.createFunction(
  {
    id: "export-to-github",
    cancelOn: [
      {
        event: "projects/export.cancelled",
        match: "data.projectId",
      },
    ],
  },
  { event: "projects/export.requested" },
  async ({ event, step }) => {
    const { projectId, repoName, accessToken } = event.data;

    // Create GitHub repository
    const repo = await step.run("create-repo", async () => {
      return await createGithubRepo(repoName, accessToken);
    });

    // Get project files
    const files = await step.run("get-files", async () => {
      return await getProjectFiles(projectId);
    });

    // Push files to GitHub
    await step.run("push-files", async () => {
      return await pushFilesToGithub(repo, files, accessToken);
    });
  }
);

Triggering jobs

Trigger jobs by sending events:
import { inngest } from "@/inngest/client";

// Trigger GitHub import
await inngest.send({
  name: "projects/import.requested",
  data: {
    projectId: "abc123",
    repoUrl: "https://github.com/user/repo",
    accessToken: "ghp_..."
  }
});

// Trigger AI processing
await inngest.send({
  name: "messages/process.requested",
  data: {
    messageId: "msg_123",
    conversationId: "conv_456"
  }
});

Cancelling jobs

Cancel running jobs by sending a cancellation event:
await inngest.send({
  name: "messages/process.cancelled",
  data: {
    messageId: "msg_123"
  }
});

Monitoring

View job status in the Inngest dashboard:
  1. Open http://localhost:8288 (dev) or your Inngest dashboard (prod)
  2. See all running, completed, and failed jobs
  3. View logs and step-by-step execution
  4. Retry failed jobs manually

Error handling

Inngest automatically retries failed jobs with exponential backoff:
export const myJob = inngest.createFunction(
  {
    id: "my-job",
    retries: 3, // Retry up to 3 times
  },
  { event: "my.event" },
  async ({ event, step }) => {
    await step.run("risky-operation", async () => {
      // If this throws, Inngest will retry
      return await riskyApiCall();
    });
  }
);

Production deployment

1

Create an Inngest account

Sign up at inngest.com for production hosting.
2

Configure webhook URL

Set your webhook URL to https://yourdomain.com/api/inngest.
3

Add signing key

Add your signing key to environment variables:
INNGEST_SIGNING_KEY=signkey_...

Learn more

Build docs developers (and LLMs) love