> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/administration-guide/lifecycle/onboarding-patterns.md).

# Choose an onboarding pattern

Choose between connected provisioning, manual fulfilment, SSO-only and authoritative-source onboarding by what each pattern actually requires in OpenIAM.

## What this is, and when you need it

"Onboard the application" describes six different outcomes that use different OpenIAM objects: creating accounts, offering access in a catalog, signing users in, protecting a legacy route, importing existing access, and reviewing it. This page picks the pattern before you create anything, because the wrong choice leaves an object behind that OpenIAM will keep treating as live.

The specific risk: an OpenIAM managed system is not an inert record. As soon as it is `IS_ACTIVE = 'Y'` and not manual, `ConnectorHealthCheckIDMSweeper` broadcasts a test-connection request to its connector's queue every `org.openiam.idm.connector.health.check.sweeptime` milliseconds — shipped `60000` — and `ConnectorServiceDownCheckIDMSweeper`, running every `org.openiam.idm.connector.service.down.check.sweep.time` milliseconds — shipped `300000` — emails the `MNG_SYS_CONNECTION_ERROR` template to every member of the group named by `org.openiam.defaultNotificationGroup` (shipped `SYSTEM_NOTIFICATION`) the first time no reply is found. See [Change configuration safely](/administration-guide/start/change-safely.md).

## The four patterns

| Pattern                     | Use when the outcome is                                                           | The OpenIAM objects it needs                                                                                                                                       |
| --------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Connected and automated** | OpenIAM creates, updates, disables, deletes accounts or memberships in the target | Connector definition + `MANAGED_SYS` with `CONNECTOR_ID` + `USER_OBJECT` policy map + a connector runtime consuming `<CONNECTOR_QUEUE>_Request`                    |
| **Manual fulfilment**       | OpenIAM governs and requests the access; a person applies it                      | `MANAGED_SYS` with `IS_MANUAL_SYSTEM = 'Y'` and no connector, its generated `MAN_MANAGED_SYS` resource, an owner, and an approval flow that raises a `MANUAL_TASK` |
| **SSO only**                | Users sign in; OpenIAM never touches accounts                                     | An authentication provider or OAuth client. **No managed system.**                                                                                                 |
| **Authoritative source**    | Identity data flows *into* OpenIAM                                                | `SYNCH_CONFIG` with a `SYNCH_SRC`, a validation script, a transformation script, and a match field                                                                 |

These combine. A SaaS application typically uses OIDC for sign-in, a connector for account lifecycle, requests for optional privileges, and an application campaign for review — four configurations, four independent tests.

## Connected and automated

What it actually requires, in the order the product enforces it:

1. **A connector definition.** A `PROVISION_CONNECTOR` row. Thirty-four ship — see [the shipped list](/administration-guide/lifecycle/connectors-and-managed-systems.md#connector-families-that-ship). If your target is not among them and no connector package exists for it, this pattern is not available. Creating a `PROVISION_CONNECTOR` row does not implement a runtime; it only changes which dynamic fields the managed-system form shows.
2. **A managed system with `CONNECTOR_ID` set.** A save is rejected with `CONNECTOR_REQUIRED` when no connector is selected and the system is not marked **Manual**. The form flags the connector field and disables **Save** before you get that far, so the error itself only appears to an integration posting the managed system directly.
3. **A policy map of type `USER_OBJECT`.** Without one, provisioning sends an object with no attributes and reconciliation fails outright with `POLICY_ATTRIBUTES_EMPTY_VALUE`.
4. **A running connector.** Everything above can be saved and look correct with no connector process at all.

Cost: you own the credential rotation, the attribute mapping, the failure handling and the target's schema quirks forever. Choose it when the target genuinely supports the operations you need.

## Manual fulfilment

Tick **Manual** on the managed system and leave **Connector** empty. Four things change:

| What changes                                                                                                                             | How you see it                                                                                                             |
| ---------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| The generated resource's type is `MAN_MANAGED_SYS`, not `MANAGED_SYS`                                                                    | Open the resource under **Access Control → Resource** and read its type                                                    |
| No connector is required to save                                                                                                         | The save succeeds with the connector field empty                                                                           |
| No policy-map template is copied by **Create Default Policies**                                                                          | The button is absent on a manual system                                                                                    |
| The heartbeat sweeper *deletes* any existing `TESTCONNECTION` reply instead of sending one, and the down check skips the system entirely | The Connector Status column shows a **Manual** chip rather than a status, and no `connectorreply` document is ever written |

So a manual managed system is silent: no heartbeat, no false alarms, and the dashboard shows a **Manual** chip in the Connector Status column rather than a status. Also note that the managed-system form's dynamic connector fields are **not saved at all** for a manual system — the fields accept input and the save reports success — so there is no point filling in base DNs on one. Reopen the system and read the fields back if you need to confirm it.

Fulfilment itself is a workflow concern: an approved request raises a `MANUAL_TASK` process, the pending membership is tagged `PENDING_MANUAL_ASSIGNMENT`, and completing the task clears that tag. The task is audited as `MANUAL_TASK`, so an untagged membership with no `MANUAL_TASK` entry was never fulfilled through this path. Configure the flow in [Manual fulfilment](/administration-guide/requests/fulfilment.md).

{% hint style="warning" %}
**Do not use Manual to work around a broken connector.** It silences the health check and the notification, so the integration stops reporting that it is down while continuing to look configured. Fix the connector, or deactivate the managed system.
{% endhint %}

## SSO only

If the application authenticates users through SAML, OAuth 2.0 or OIDC and OpenIAM never creates an account in it, it needs **no managed system**. Configure an authentication provider or an OAuth client — see [Configure federation and application SSO](/administration-guide/federation.md) — and, if accounts should be created on first sign-in, [Just-in-time provisioning](/administration-guide/federation/jit-provisioning.md), which is a federation mechanism and not a connector.

{% hint style="danger" %}
**Do not create a managed system purely as a catalog placeholder.** It is a common shortcut — "we want the application to appear in the request catalog, so we made a managed system for it" — and it costs you four things:

* If you leave it **Active** with a connector selected, the heartbeat broadcast fires every 60 seconds forever, and a `[ALERT] Healthcheck on <name>` email goes to the `SYSTEM_NOTIFICATION` group, because no connector will ever answer. A `SERVICE_DOWN` document stays in the `connectorreply` index for as long as the system is active.
* If you leave it **Active** with `ASSIGN_TO_ALL = 'Y'`, `addAssignToAllGroupsRolesMngSystems` adds its resource to every `ProvisionUser` on every add and update.
* If anyone later assigns it and `ON_DELETE` is absent, revoking the entitlement issues a real `Delete` to a connector that is not there, leaving the identity in `PENDING_DELETE` or `FAIL_DELETE`.
* Deleting it later is blocked once anyone has a `LOGIN` row on it — the refusal is `LINKED_TO_USERS`, and its message carries the login count.

What to do instead: catalog visibility comes from a **resource** in an `APPLICATION_CATEGORY`, not from a managed system. Create the resource. If you additionally need to govern who has access and be honest that OpenIAM cannot apply it, use the **manual** pattern — which is exactly what it is for.
{% endhint %}

## Authoritative source

The source of identity data, not a provisioning target. Configured on `SYNCH_CONFIG`, whose `SYNCH_SRC` column takes one of these values:

| `SYNCH_SRC`       | UI label                    | What it reads                                                                                        | Notes                                                                      |
| ----------------- | --------------------------- | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `CSV`             | CSV file                    | An uploaded file selected in **CSV File Name**, split on `SPLITTER`                                  | `MANAGED_SYS_ID` is `0` in every shipped example                           |
| `RDBMS`           | RDBMS                       | `QUERY` over a JDBC connection built from `DRIVER`, `CONNECTION_URL`, `SRC_LOGIN_ID`, `SRC_PASSWORD` | OpenIAM connects directly; no connector involved                           |
| `CONNECTOR_ASYNC` | Connector — Single-Threaded | The managed system named by `MANAGED_SYS_ID`, through its connector                                  | **Requires a managed system whose heartbeat is `Ok`** — see below          |
| `CUSTOM`          | Custom Adapter              | Whatever `CUSTOM_ADAPTER_SCRIPT_ID` implements                                                       | Your code becomes production code                                          |
| `LOG`             | LOG file                    | OpenIAM audit events                                                                                 | Thread count from `synchronization.log.adapter.thread.number`, default `1` |

`CONNECTOR_ASYNC` is the one that couples the two patterns: `SyncConfigRestController.startSynch` calls `asynchSynchServiceWS.testConnection(config)` *before* starting, and for a connector source `ConnectorAdapter.testConnection` is `provisionMQService.testConnectionConfig(config.getManagedSysId())` — the same heartbeat lookup described in [Verify connectivity to the target](/administration-guide/lifecycle/verify-connection.md). A directory-source synchronization therefore refuses to start with `FAIL_CONNECTION` while the managed system's heartbeat is missing, even though the synchronization only intends to read.

{% hint style="info" %}
`SYNCH_SRC` used to have a `CONNECTOR` value. As of 4.2.2.0 every configuration holding it was rewritten to `CONNECTOR_ASYNC`, so on a current build every shipped example config reads `CONNECTOR_ASYNC` — and if a query finds a config still reading `CONNECTOR`, it was created after that upgrade and is wrong. The label key `openiam.ui.webconsole.idm.sync.config.CONNECTOR` is still in `messages_en.properties` ("Connector — Single-Threaded") because it is the label for `CONNECTOR_ASYNC`.
{% endhint %}

Decide **Provision to target systems?** (`IS_PROVISION`) deliberately. Off, the transformation's result is saved to the OpenIAM database only. On, the same result is handed to the provisioning service, which then reaches every managed system the identity is entitled to. And leave **Detect orphans** (`IS_ORPHAN_DETECTION`) off for an authoritative source: with it on, `UserSyncObjectProcessorImpl.addOrphan` intercepts every record the match rule could not tie to an existing user, writes it to the `orphan` index, audits `SYNCHRONIZATION_ORPHAN`, and **returns before the record is saved**. A joiner feed with orphan detection on creates nobody. See [Set up a synchronization](/administration-guide/lifecycle/synchronize-and-import-data.md).

## Deciding

Answer these five in writing before you create an object. They map one-to-one onto configuration.

| Question                                                                              | What it decides                                                                                                                                           |
| ------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Does OpenIAM change anything in the target?                                           | Connected/manual vs SSO-only. "No" means no managed system.                                                                                               |
| Does a connector definition exist for this target, and is a runtime deployed?         | Connected vs manual. A definition with no runtime is manual with extra alarms.                                                                            |
| Which immutable value correlates a source record to an OpenIAM person?                | `SYNCH_CONFIG.MATCH_FIELD_NAME` / `MATCH_SRC_FIELD_NAME`. Never a display name; never `sAMAccountName`, which is mutable and absent for cloud-only users. |
| Is the access mandatory for a population, or requested by an individual?              | `ASSIGN_TO_ALL` / a business rule vs a request category. Never both for the same grant — removal becomes unpredictable.                                   |
| When entitlement is revoked, must the target account be deleted, disabled or updated? | The `ON_DELETE` resource property. Absent means **delete**.                                                                                               |

## Worked comparison: the same application, three ways

An HR system, `<MANAGED_SYSTEM_ID>` aside.

**As an authoritative source.** `SYNCH_CONFIG` with `SYNCH_SRC = 'RDBMS'`, `PROCESS_RULE = 'USER'`, `SYNCH_TYPE = 'FULL'`, `MANAGED_SYS_ID = '0'`, `MATCH_FIELD_NAME = 'EMPLOYEE_ID'`, `MATCH_SRC_FIELD_NAME = 'EMP_ID'`, `IS_PROVISION = 'N'` for the first runs. This is exactly the shipped `MySQL DB Example` configuration, whose scripts are `sync/user/db/DBSampleValidationScript.groovy` and `sync/user/db/DBSampleTransformationScript.groovy`. No managed system for HR is needed at all.

**As a provisioning target.** Only if OpenIAM must write back. That needs a connector definition for the HR product, a managed system, and a policy map — a different and much larger project.

**As a governed application with no API.** Manual managed system, `MAN_MANAGED_SYS` resource, owner assigned, roles imported by a CSV synchronization with `PROCESS_RULE = 'ROLE'`, and an application campaign over the result.

Most HR onboardings are the first. Deciding that early is the whole point of this page.

## Verification

You have chosen correctly when:

* Every object you created is one the pattern's table above lists. An extra managed system is a signal you chose SSO-only or catalog and built connected anyway.
* `SELECT MANAGED_SYS_ID, NAME, IS_MANUAL_SYSTEM, IS_ACTIVE, CONNECTOR_ID, ASSIGN_TO_ALL FROM MANAGED_SYS` contains no row that is active, non-manual, and pointed at a connector nobody deployed.
* For the authoritative-source pattern, the sync config's `MANAGED_SYS_ID` is `0` unless the source is read through a connector.

## When it goes wrong

| Symptom                                                                  | Cause                                                                                                                                                                                                   | Fix                                                                                                                   |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- |
| **Save** disabled on the managed-system form, no message                 | `!manual && !connectorId` sets an error on `connectionId` in `ManagedSystemScreen`                                                                                                                      | Select a connector, or tick **Manual**. Do not tick Manual to bypass a missing connector.                             |
| Save rejected with `CONNECTOR_REQUIRED`                                  | Same condition, server side                                                                                                                                                                             | As above.                                                                                                             |
| `[ALERT] Healthcheck on <name>` email for a system nobody uses           | An active, non-manual managed system with a connector nobody deployed; `ConnectorServiceDownCheckIDMSweeper` saved a `SERVICE_DOWN` doc and notified the `org.openiam.defaultNotificationGroup` members | Untick **Active**, or delete the managed system. The sweeper then deletes the `TESTCONNECTION` docs on its next pass. |
| Application appears in the catalog but requests never reach a target     | SSO-only or catalog-placeholder managed system with no runtime                                                                                                                                          | Convert to **Manual** so fulfilment produces a task, or deploy a connector.                                           |
| Directory-source synchronization refuses to start with `FAIL_CONNECTION` | `startSynch` tests the managed system's heartbeat first, and it has none                                                                                                                                | Fix the connector — [Verify connectivity to the target](/administration-guide/lifecycle/verify-connection.md).        |
| Authoritative import runs, reads every record, creates nobody            | **Detect orphans** is ticked; unmatched records go to the `orphan` index                                                                                                                                | Untick `IS_ORPHAN_DETECTION`.                                                                                         |
| Managed system cannot be deleted                                         | `LINKED_TO_USERS` (a `LOGIN` row exists), `LINKED_TO_AUTHENTICATION_PROVIDER`, or `LINKED_TO_ACCESS_RIGHTS`                                                                                             | [Decommission a managed system](/administration-guide/lifecycle/decommission-a-managed-system.md).                    |

## Related

* [Connectors and managed systems](/administration-guide/lifecycle/connectors-and-managed-systems.md) — what ships, and which guide owns what.
* [Configure a managed system](/administration-guide/lifecycle/configure-managed-system.md) — the form, field by field, with per-connector values.
* [Set up a synchronization](/administration-guide/lifecycle/synchronize-and-import-data.md) — the authoritative-source procedure.
* [Manual fulfilment](/administration-guide/requests/fulfilment.md) — the reviewer and fulfiller side of the manual pattern.
* [Configure federation and application SSO](/administration-guide/federation.md) — the SSO-only pattern.

*Applies to OpenIAM 2026.8.1. Last reviewed 7 August 2026.*


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/administration-guide/lifecycle/onboarding-patterns.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
