# Background daemons

Background daemons are standalone Node.js services that run alongside the Comind.work platform. They handle recurring tasks like file synchronization, email polling, and messaging bot integrations.

## Architecture[​](#architecture "Direct link to Architecture")

Background daemons are **not part of the app engine** - they run as separate processes managed by PM2 or system cron.

Available integrations:

| Daemon         | Purpose                                                         |
| -------------- | --------------------------------------------------------------- |
| `sftp-sync`    | Synchronize files between Comind.work and external SFTP servers |
| `gmail-sync`   | Poll Gmail accounts and create records from incoming emails     |
| `telegram-bot` | Relay messages between Telegram chats and Comind.work records   |
| `data-import`  | Batch import data from external sources on a schedule           |
| `demo-data`    | Generate sample data for demo workspaces                        |

## Building a background daemon[​](#building-a-background-daemon "Direct link to Building a background daemon")

A background daemon is a Node.js script that:

1. Connects to the Comind.work API using service credentials
2. Performs its task (poll, sync, transform)
3. Exits or sleeps until the next cycle

### Project structure[​](#project-structure "Direct link to Project structure")

```
ext-integrations/
└── my-daemon/
    ├── package.json
    ├── index.js            # Entry point
    ├── config.js            # Environment-specific settings
    └── ecosystem.config.js  # PM2 configuration
```

### PM2 configuration[​](#pm2-configuration "Direct link to PM2 configuration")

Use PM2 to manage daemon processes in production:

```
// ecosystem.config.js
module.exports = {
  apps: [{
    name: "my-daemon",
    script: "./src/my-daemon.cjs",
    cron_restart: "*/15 * * * *",  // restart every 15 minutes
    instances: 1,
    error_file: "./err.log",
    out_file: "./out.log",
  }],
};
```

Environment variables (API URL, auth tokens) are loaded from the system environment or `.env` files, not from the PM2 config.

### Connecting to the API[​](#connecting-to-the-api "Direct link to Connecting to the API")

Daemons use the Comind.work REST API to read and write data:

Comind.work uses a custom authorization scheme, not Bearer tokens. The header format is `Authorization: CMW_AUTH_CODE {token}`.

```
const axios = require("axios");

const api = axios.create({
  baseURL: process.env.CMW_API_URL + "/api",
  headers: {
    Authorization: `CMW_AUTH_CODE ${process.env.CMW_API_TOKEN}`
  }
});

// Example: fetch records
const response = await api.get("/records/WORKSPACE/APP", {
  params: { filter: 'state="open"', limit: 50 }
});
```

If using the Comind.work SDK, you can call `RestApi.setComindAuth()` to set the header automatically.

## SFTP sync example[​](#sftp-sync-example "Direct link to SFTP sync example")

The SFTP sync daemon monitors a remote SFTP server and creates or updates file records in Comind.work when new files appear.

Typical workflow:

1. Connect to the SFTP server using configured credentials
2. List files in the monitored directory
3. Compare against existing Comind.work records (by filename or hash)
4. Download new files and create records with attachments
5. Optionally move processed files to an archive directory

## Gmail sync[​](#gmail-sync "Direct link to Gmail sync")

The Gmail sync daemon polls a Gmail account via the Gmail API and creates records from incoming messages.

Workflow:

1. Authenticate with Gmail using OAuth2 or service account credentials
2. Query for unread messages matching configured filters (labels, senders, subjects)
3. Parse email content (subject, body, attachments)
4. Create a new record in the target app with email data mapped to fields
5. Mark the email as processed (label or archive)

## Deployment[​](#deployment "Direct link to Deployment")

### Using PM2[​](#using-pm2 "Direct link to Using PM2")

```
# Start the daemon
pm2 start ecosystem.config.js

# Monitor running daemons
pm2 list
pm2 logs my-daemon

# Set up PM2 to survive reboots
pm2 startup
pm2 save
```

### Using system cron[​](#using-system-cron "Direct link to Using system cron")

For simple one-shot tasks, use cron instead of PM2:

```
# Run every 15 minutes
*/15 * * * * cd /path/to/my-daemon && node index.js >> /var/log/my-daemon.log 2>&1
```

## Best practices[​](#best-practices "Direct link to Best practices")

* **Idempotency** - design each run to be safe to repeat. Use unique keys (filenames, email IDs) to detect duplicates.
* **Error handling** - log errors and continue processing remaining items. A single bad record should not stop the entire sync.
* **Rate limiting** - respect Comind.work API rate limits. Add delays between batch operations.
* **Configuration** - use environment variables for all connection details. Never hardcode credentials.
* **Monitoring** - use PM2 monitoring or external health checks to detect daemon failures.

## Related[​](#related "Direct link to Related")

* [Scheduled jobs](/admin-guide/workspace-admin/jobs.md) - admin-guide coverage of background jobs and scheduled processing from the workspace admin perspective
* [External API calls](/developer-guide/how-to/advanced/external-api-calls.md) - the `RestApi` pattern used by daemons to communicate with Comind.work
