> ## Documentation Index
> Fetch the complete documentation index at: https://translations.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Importation en bloc de données utilisateur dans les connexions à une base de données Auth0

> Migrez des utilisateurs d’une base de données ou d’un service existant vers Auth0 à l’aide d’importations en bloc pour les connexions à une base de données.

export const AuthCodeGroup = ({children, dropdown}) => {
  const [processedChildren, setProcessedChildren] = useState(children);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      unsubscribe = window.autorun(() => {
        const processChildren = node => {
          if (typeof node === "string") {
            let processedNode = node;
            for (const [key, value] of window.rootStore.variableStore.values.entries()) {
              const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
              processedNode = processedNode.replaceAll(new RegExp(escapedKey, "g"), value);
            }
            return processedNode;
          } else if (Array.isArray(node)) {
            return node.map(processChildren);
          } else if (node && node.props && node.props.children) {
            return {
              ...node,
              props: {
                ...node.props,
                children: processChildren(node.props.children)
              }
            };
          }
          return node;
        };
        setProcessedChildren(processChildren(children));
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  return <CodeGroup dropdown={dropdown}>{processedChildren}</CodeGroup>;
};

export const AuthCodeBlock = ({filename, icon, language, highlight, children}) => {
  const [displayText, setDisplayText] = useState(children);
  const [copyText, setCopyText] = useState(children);
  const wrapperRef = React.useRef(null);
  useEffect(() => {
    let unsubscribe = null;
    function init() {
      if (!window.autorun || !window.rootStore) {
        return;
      }
      unsubscribe = window.autorun(() => {
        let processedChildrenForDisplay = children;
        let processedChildrenForCopy = children;
        for (const [key, value] of window.rootStore.variableStore.values.entries()) {
          const escapedKey = key.replaceAll(/[.*+?^${}()|[\]\\]/g, (String.raw)`\$&`);
          let displayValue = value;
          if (key === "{yourClientSecret}" && value !== "{yourClientSecret}") {
            displayValue = value.substring(0, 3) + "*****MASQUÉ*****";
          }
          processedChildrenForDisplay = processedChildrenForDisplay.replaceAll(new RegExp(escapedKey, "g"), displayValue);
          processedChildrenForCopy = processedChildrenForCopy.replaceAll(new RegExp(escapedKey, "g"), value);
        }
        setDisplayText(processedChildrenForDisplay);
        setCopyText(processedChildrenForCopy);
      });
    }
    if (window.rootStore) {
      init();
    } else {
      window.addEventListener("adu:storeReady", init);
    }
    return () => {
      window.removeEventListener("adu:storeReady", init);
      unsubscribe?.();
    };
  }, [children]);
  useEffect(() => {
    if (!wrapperRef.current) return;
    const originalWriteText = navigator.clipboard.writeText.bind(navigator.clipboard);
    let isOverriding = false;
    const handleClick = e => {
      const button = e.target.closest('[data-testid="copy-code-button"]');
      if (!button || !wrapperRef.current.contains(button)) return;
      isOverriding = true;
      navigator.clipboard.writeText = text => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
          return originalWriteText(copyText);
        }
        return originalWriteText(text);
      };
      setTimeout(() => {
        if (isOverriding) {
          isOverriding = false;
          navigator.clipboard.writeText = originalWriteText;
        }
      }, 100);
    };
    const wrapper = wrapperRef.current;
    wrapper.addEventListener('click', handleClick, true);
    return () => {
      wrapper.removeEventListener('click', handleClick, true);
      if (navigator.clipboard.writeText !== originalWriteText) {
        navigator.clipboard.writeText = originalWriteText;
      }
    };
  }, [copyText]);
  return <div ref={wrapperRef}>
      <CodeBlock filename={filename} icon={icon} language={language} lines highlight={highlight}>
        {displayText}
      </CodeBlock>
    </div>;
};

Vous pouvez importer en bloc des données utilisateur existantes dans une connexion à une base de données Auth0. Cela peut être utile pour migrer des utilisateurs d’une base de données ou d’un service existant vers Auth0.

Pour importer en bloc des données utilisateur, créez d’abord un fichier de données utilisateur au format JSON attendu par Auth0, puis lancez une tâche pour importer ces données à l’aide du Dashboard ou de la Management API.

<div id="prerequisites">
  ## Prérequis
</div>

<Tabs>
  <Tab title="Auth0 Dashboard">
    * Vous devez disposer d’une [connexion à une base de données](/docs/fr-ca/authenticate/database-connections) dans laquelle importer les données utilisateur. Il peut s’agir de l’une des connexions suivantes :
      * Une connexion à une base de données utilisant le répertoire d’utilisateurs d’Auth0.
      * Une [connexion à une base de données personnalisée](/docs/fr-ca/authenticate/database-connections/custom-db) utilisant votre répertoire d’utilisateurs externe, avec le mode d’importation activé.

    * Vous devez disposer de l’un des [rôles de membre du tenant](/docs/fr-ca/get-started/manage-dashboard-access/feature-access-by-role) suivants :
      * **Admin**
      * **Editor - Users**
  </Tab>

  <Tab title="Management API">
    * Vous devez disposer d’une [connexion à une base de données](/docs/fr-ca/authenticate/database-connections) dans laquelle importer les données utilisateur. Il peut s’agir de l’une des connexions suivantes :
      * Une connexion à une base de données utilisant le répertoire d’utilisateurs d’Auth0.
      * Une [connexion à une base de données personnalisée](/docs/fr-ca/authenticate/database-connections/custom-db) utilisant votre répertoire d’utilisateurs externe, avec le mode d’importation activé.

    * Vous devez disposer d’un [jeton Management API](/docs/fr-ca/secure/tokens/access-tokens/management-api-access-tokens) ou en créer un pour effectuer des requêtes vers le endpoint des tâches, avec les scopes nécessaires pour le [endpoint Create import users job](/docs/fr-ca/api/management/v2/jobs/post-users-imports).
  </Tab>
</Tabs>

<div id="1-create-the-user-data-file">
  ## 1. Créer le fichier de données utilisateur
</div>

Commencez par mettre vos données utilisateur existantes au format JSON afin de les importer dans Auth0, en respectant la structure définie dans le [schéma JSON des données utilisateur et la référence des propriétés](/docs/fr-ca/manage-users/user-migration/bulk-user-import-database-schema-and-examples).

Les points suivants peuvent vous être utiles lors de la création du fichier de données utilisateur :

* La taille maximale d’un fichier pour une importation en bloc est de 500 Ko. Si vos données dépassent cette limite, vous devez les répartir dans plusieurs fichiers plus petits à téléverser dans le cadre de plusieurs tâches.

  À titre indicatif, un fichier contenant environ 1 000 utilisateurs et moins de 10 champs de métadonnées par utilisateur respecte généralement cette limite de taille.

* Si vous partez d’une [exportation de données utilisateur Auth0](/docs/fr-ca/manage-users/user-migration/bulk-user-exports) :

  * Les importations en bloc prennent en charge le format JSON, mais les exportations d’utilisateurs générées par Auth0 sont au format [NDJSON](https://github.com/ndjson/ndjson-spec). Vous pouvez convertir le format NDJSON en JSON à l’aide d’outils comme [`jq`](https://jqlang.org/).

  * Les importations en bloc ajoutent automatiquement le préfixe `auth0|` aux ID des utilisateurs importés, mais les exportations d’utilisateurs générées par Auth0 comportent déjà ce préfixe dans les ID utilisateur.

  Pour conserver les mêmes ID utilisateur, supprimez le préfixe `auth0|` de tous les ID utilisateur importés. Sinon, les ID utilisateur comporteront le préfixe deux fois (`auth0|auth0|<user_id>`).

* Vous pouvez importer des données utilisateur avec des mots de passe hachés à l’aide d’un [algorithme pris en charge](./bulk-user-import-schema#param-algorithm). Les utilisateurs dont les mots de passe sont hachés à l’aide d’algorithmes non pris en charge doivent réinitialiser leur mot de passe lorsqu’ils se connectent pour la première fois après l’importation en bloc.

  Si un utilisateur ne s’est pas connecté à l’aide du `custom_password_hash` importé initialement, vous pouvez le mettre à jour en soumettant de nouveau les données utilisateur avec une valeur différente pour `custom_password_hash` dans une nouvelle tâche avec les upserts activés.

<div id="2-import-the-user-data-into-your-database-connection">
  ## 2. Importez les données utilisateur dans votre connexion à une base de données
</div>

<Tabs>
  <Tab title="Auth0 Dashboard">
    Pour importer des données utilisateur à l’aide du Auth0 Dashboard :

    1. Accédez à [**Dashboard > Gestion des utilisateurs > Utilisateurs**](https://manage.auth0.com/#/users).

    2. Dans le coin supérieur droit de la page, sélectionnez **Importer/exporter des utilisateurs** pour accéder à la page **Importer/exporter des utilisateurs**.

    3. Sélectionnez **Importer des utilisateurs** pour accéder à la page **Importer des utilisateurs**.

           <Frame>
             <img src="https://mintcdn.com/translations/mMSz-RNYLuOm2GmQ/docs/images/cdy7uua7fh8z/KrknYhAUOaYBzzBrgHp4M/b2389f5926122a306eab10e54b917da6/import.png?fit=max&auto=format&n=mMSz-RNYLuOm2GmQ&q=85&s=82d3a5fe838c13ea26eee50e388ee421" alt="" width="1999" height="1444" data-path="docs/images/cdy7uua7fh8z/KrknYhAUOaYBzzBrgHp4M/b2389f5926122a306eab10e54b917da6/import.png" />
           </Frame>

    4. Sous **Fichier JSON des utilisateurs**, sélectionnez **+ Choisir un fichier** et téléversez le fichier JSON des données utilisateur.

    5. Sous **Connexion**, ouvrez le menu déroulant et sélectionnez la connexion de base de données dans laquelle vous souhaitez importer les données utilisateur.

    6. Facultativement, cochez **Mettre à jour les utilisateurs préexistants dans la connexion**. Lorsqu’un utilisateur importé correspond à un utilisateur existant dans la connexion de base de données, vous pouvez choisir de mettre à jour les données ou non :

       * Par défaut, les mises à jour sont désactivées. Les importations d’utilisateurs correspondant à une adresse courriel, un ID utilisateur, un téléphone ou un username échouent.

       * Lorsque les mises à jour sont activées, les importations d’utilisateurs correspondant à une adresse courriel mettent à jour tous les [attributs pouvant être mis à jour](/docs/fr-ca/manage-users/user-migration/bulk-user-import-database-schema-and-examples).

    7. Facultativement, cochez **Envoyer un courriel de fin d’opération à tous les propriétaires du tenant**. Lorsque cette option est activée, un courriel de fin d’opération est envoyé à tous les administrateurs de tenant lorsque le job réussit ou échoue.

    8. Pour soumettre le job, sélectionnez **Importer des utilisateurs**.
  </Tab>

  <Tab title="API de Management">
    Pour importer des données d’utilisateurs à l’aide de la Management API, appelez le [point de terminaison Create Import Users Job](/docs/fr-ca/api/management/v2/jobs/post-users-imports) (`POST /jobs/users-imports`). Consultez la documentation du point de terminaison pour connaître les détails des paramètres du corps de la requête et des schémas de réponse.

    Pour utiliser les exemples ci-dessous :

    * Remplacez les variables fictives `MGMT_API_ACCESS_TOKEN`, `USERS_IMPORT_FILE.json`, `CONNECTION_ID` et `EXTERNAL_ID` par vos propres valeurs.

          <Tip>
            Vous pouvez [consulter l’ID de la connexion à la base de données dans le Dashboard](/docs/fr-ca/authenticate/identity-providers/locate-the-connection-id) ou l’obtenir à l’aide du [endpoint Get all connections](/docs/fr-ca/api/management/v2/connections/get-connections) de la Management API.
          </Tip>

    * Vous pouvez également définir `upsert`. Lorsqu’un utilisateur importé correspond à un utilisateur existant dans la connexion à la base de données, vous pouvez choisir de mettre à jour ou non les données :

      * Par défaut, les opérations d’upsert sont désactivées. Les importations d’utilisateurs dont l’adresse courriel, l’ID utilisateur, le numéro de téléphone ou le nom d’utilisateur correspondent échouent.

      * Lorsque `upsert` est activé, les importations d’utilisateurs dont l’adresse courriel correspond mettent à jour tous les [attributs pouvant être mis à jour](/docs/fr-ca/manage-users/user-migration/bulk-user-import-database-schema-and-examples).

    * Facultativement, définissez \`send\_completion\_email afin d’envoyer un courriel de confirmation à tous les administrateurs de tenant lorsque le job réussit ou échoue.

    <AuthCodeGroup>
      ```bash cURL theme={null}
      curl --request POST \
        --url 'https://{yourDomain}/api/v2/jobs/users-imports' \
        --header 'authorization: Bearer MGMT_API_ACCESS_TOKEN' \
        --form users=@USERS_IMPORT_FILE.json \
        --form connection_id=CONNECTION_ID \
        --form external_id=EXTERNAL_ID
      ```

      ```csharp C# theme={null}
      var client = new RestClient("https://{yourDomain}/api/v2/jobs/users-imports");
      var request = new RestRequest(Method.POST);
      request.AddHeader("authorization", "Bearer MGMT_API_ACCESS_TOKEN");
      request.AddHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001");
      request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r
      Content-Disposition: form-data; name="users"; filename="USERS_IMPORT_FILE.json"\r
      Content-Type: text/json\r
      \r
      \r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="connection_id"\r
      \r
      CONNECTION_ID\r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="external_id"\r
      \r
      EXTERNAL_ID\r
      -----011000010111000001101001--\r
      ", ParameterType.RequestBody);
      IRestResponse response = client.Execute(request);
      ```

      ```go Go theme={null}
      package main

      import (
      	"fmt"
      	"strings"
      	"net/http"
      	"io/ioutil"
      )

      func main() {

      	url := "https://{yourDomain}/api/v2/jobs/users-imports"

      	payload := strings.NewReader("-----011000010111000001101001\r
      Content-Disposition: form-data; name="users"; filename="USERS_IMPORT_FILE.json"\r
      Content-Type: text/json\r
      \r
      \r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="connection_id"\r
      \r
      CONNECTION_ID\r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="external_id"\r
      \r
      EXTERNAL_ID\r
      -----011000010111000001101001--\r
      ")

      	req, _ := http.NewRequest("POST", url, payload)

      	req.Header.Add("authorization", "Bearer MGMT_API_ACCESS_TOKEN")
      	req.Header.Add("content-type", "multipart/form-data; boundary=---011000010111000001101001")

      	res, _ := http.DefaultClient.Do(req)

      	defer res.Body.Close()
      	body, _ := ioutil.ReadAll(res.Body)

      	fmt.Println(res)
      	fmt.Println(string(body))

      }
      ```

      ```java Java theme={null}
      HttpResponse<String> response = Unirest.post("https://{yourDomain}/api/v2/jobs/users-imports")
        .header("authorization", "Bearer MGMT_API_ACCESS_TOKEN")
        .header("content-type", "multipart/form-data; boundary=---011000010111000001101001")
        .body("-----011000010111000001101001\r
      Content-Disposition: form-data; name="users"; filename="USERS_IMPORT_FILE.json"\r
      Content-Type: text/json\r
      \r
      \r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="connection_id"\r
      \r
      CONNECTION_ID\r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="external_id"\r
      \r
      EXTERNAL_ID\r
      -----011000010111000001101001--\r
      ")
        .asString();
      ```

      ```javascript Node.JS theme={null}
      var axios = require("axios").default;

      var options = {
        method: 'POST',
        url: 'https://{yourDomain}/api/v2/jobs/users-imports',
        headers: {
          authorization: 'Bearer MGMT_API_ACCESS_TOKEN',
          'content-type': 'multipart/form-data; boundary=---011000010111000001101001'
        },
        data: '-----011000010111000001101001\r
      Content-Disposition: form-data; name="users"; filename="USERS_IMPORT_FILE.json"\r
      Content-Type: text/json\r
      \r
      \r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="connection_id"\r
      \r
      CONNECTION_ID\r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="external_id"\r
      \r
      EXTERNAL_ID\r
      -----011000010111000001101001--\r
      '
      };

      axios.request(options).then(function (response) {
        console.log(response.data);
      }).catch(function (error) {
        console.error(error);
      });
      ```

      ```php PHP theme={null}
      $curl = curl_init();

      curl_setopt_array($curl, [
        CURLOPT_URL => "https://{yourDomain}/api/v2/jobs/users-imports",
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_ENCODING => "",
        CURLOPT_MAXREDIRS => 10,
        CURLOPT_TIMEOUT => 30,
        CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
        CURLOPT_CUSTOMREQUEST => "POST",
        CURLOPT_POSTFIELDS => "-----011000010111000001101001\r
      Content-Disposition: form-data; name="users"; filename="USERS_IMPORT_FILE.json"\r
      Content-Type: text/json\r
      \r
      \r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="connection_id"\r
      \r
      CONNECTION_ID\r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="external_id"\r
      \r
      EXTERNAL_ID\r
      -----011000010111000001101001--\r
      ",
        CURLOPT_HTTPHEADER => [
          "authorization: Bearer MGMT_API_ACCESS_TOKEN",
          "content-type: multipart/form-data; boundary=---011000010111000001101001"
        ],
      ]);

      $response = curl_exec($curl);
      $err = curl_error($curl);

      curl_close($curl);

      if ($err) {
        echo "cURL Error #:" . $err;
      } else {
        echo $response;
      }
      ```

      ```python Python theme={null}
      import http.client

      conn = http.client.HTTPSConnection("{yourDomain}")

      # Lire le fichier d'importation des utilisateurs
      with open("USERS_IMPORT_FILE.json", "rb") as f:
          file_contents = f.read()

      payload = (
          "-----011000010111000001101001\r\n"
          "Content-Disposition: form-data; name=\"users\"; filename=\"USERS_IMPORT_FILE.json\"\r\n"
          "Content-Type: application/json\r\n"
          "\r\n"
          + file_contents.decode("utf-8") + "\r\n"
          "-----011000010111000001101001\r\n"
          "Content-Disposition: form-data; name=\"connection_id\"\r\n"
          "\r\n"
          "CONNECTION_ID\r\n"
          "-----011000010111000001101001\r\n"
          "Content-Disposition: form-data; name=\"external_id\"\r\n"
          "\r\n"
          "EXTERNAL_ID\r\n"
          "-----011000010111000001101001--\r\n"
      )

      headers = {
          'authorization': "Bearer MGMT_API_ACCESS_TOKEN",
          'content-type': "multipart/form-data; boundary=---011000010111000001101001"
          }

      conn.request("POST", "/api/v2/jobs/users-imports", payload, headers)

      res = conn.getresponse()
      data = res.read()

      print(data.decode("utf-8"))
      ```

      ```ruby Ruby theme={null}
      require 'uri'
      require 'net/http'
      require 'openssl'

      url = URI("https://{yourDomain}/api/v2/jobs/users-imports")

      http = Net::HTTP.new(url.host, url.port)
      http.use_ssl = true
      http.verify_mode = OpenSSL::SSL::VERIFY_PEER

      request = Net::HTTP::Post.new(url)
      request["authorization"] = 'Bearer MGMT_API_ACCESS_TOKEN'
      request["content-type"] = 'multipart/form-data; boundary=---011000010111000001101001'
      request.body = "-----011000010111000001101001\r
      Content-Disposition: form-data; name="users"; filename="USERS_IMPORT_FILE.json"\r
      Content-Type: text/json\r
      \r
      \r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="connection_id"\r
      \r
      CONNECTION_ID\r
      -----011000010111000001101001\r
      Content-Disposition: form-data; name="external_id"\r
      \r
      EXTERNAL_ID\r
      -----011000010111000001101001--\r
      "

      response = http.request(request)
      puts response.read_body
      ```
    </AuthCodeGroup>

    Lorsque la création d'une tâche réussit, la valeur retournée contient des renseignements sur la tâche, dont son ID.
  </Tab>
</Tabs>

<div id="3-check-job-status">
  ## 3. Vérifier le statut d’une tâche
</div>

<Tabs>
  <Tab title="Auth0 Dashboard">
    Pour vérifier le statut d’une tâche :

    1. Accédez à [**Dashboard > User Management > Users**](https://manage.auth0.com/#/users).

    2. Dans le coin supérieur droit de la page, sélectionnez **Import/Export Users** pour accéder à la page **Import/Export Users**. Une fois que vous avez lancé au moins une tâche, cette page répertorie les tâches que vous avez soumises.

    3. Pour afficher plus de renseignements sur une tâche, sélectionnez **More info** à côté de celle-ci.

    Les statuts des tâches comprennent **Job creation failed**, **Job created, user import failed** et **Job created, user import succeeded**.
  </Tab>

  <Tab title="Management API">
    Pour vérifier le statut d’une tâche, envoyez une requête au [endpoint Get a job](/docs/fr-ca/api/management/v2/jobs/get-jobs-by-id) (`GET /jobs`) avec l’ID de la tâche. Consultez la documentation de l’endpoint pour en savoir plus sur ses paramètres et les schémas de réponse.

    Le `status` de la tâche renvoyée peut être `pending`, `completed` ou `failed`. Si la tâche est terminée, l’objet `summary` de la réponse inclut le total des enregistrements réussis, échoués, insérés et mis à jour.

    Si une tâche échoue, vous pouvez obtenir les détails de l’erreur en envoyant une requête au [endpoint Get job error details](https://auth0.com/docs/api/management/v2#!/Jobs/get_errors) (`GET /jobs/{id}/errors`) avec l’ID de la tâche. Chaque objet d’erreur de la réponse comprend un code d’erreur et un message expliquant l’erreur plus en détail. Les codes d’erreur possibles sont :

    * `ANY_OF_MISSING`
    * `ARRAY_LENGTH_LONG`
    * `ARRAY_LENGTH_SHORT`
    * `CONFLICT`
    * `CONFLICT_EMAIL`
    * `CONFLICT_USERNAME`
    * `CONNECTION_NOT_FOUND`
    * `DUPLICATED_USER`
    * `ENUM_MISMATCH`
    * `FORMAT`
    * `INVALID_TYPE`
    * `MAX_LENGTH`
    * `MAXIMUM`
    * `MFA_FACTORS_FAILED`
    * `MIN_LENGTH`
    * `MINIMUM`
    * `NOT_PASSED`
    * `OBJECT_REQUIRED`
    * `PATTERN`
  </Tab>
</Tabs>

Les tâches échouent en cas d’erreur, mais non lorsque les renseignements utilisateur sont non valides (par exemple, une adresse courriel non valide).

<div id="limits">
  ## Limites
</div>

* Un maximum de deux tâches d’importation peut s’exécuter simultanément par tenant.

* Les tâches d’importation d’utilisateurs expirent après deux (2) heures. Si une tâche ne se termine pas dans ce délai, elle est marquée comme ayant échoué.

* Toutes les données associées aux tâches sont automatiquement supprimées après 24 heures.

* Les entrées d’utilisateurs en double dans le fichier d’importation entraînent une erreur. Elles ne donnent pas lieu à une importation suivie d’un upsert.

* Les upserts ne fusionnent ni `user_metadata` ni `app_metadata`. Les métadonnées existantes sont entièrement remplacées par les nouvelles métadonnées.

<div id="best-practices-for-large-scale-migrations">
  ## Bonnes pratiques pour les migrations à grande échelle
</div>

Lors de l’importation de grandes quantités de données utilisateur (nécessitant 10 tâches ou plus), nous recommandons les stratégies suivantes :

* **Utilisez un framework de planification de tâches** (comme [Bull](https://github.com/OptimalBits/bull) ou [Agenda](https://github.com/agenda/agenda)). Cela vous permet de :

  * Respecter la limite de concurrence requise.

  * Prévoir une stratégie de reprise pour gérer les interruptions de connexion réseau et les échecs temporaires.

  * Conserver les résultats des tâches et les détails des erreurs au-delà de la période de suppression.

* **N’interrompez pas les importations en cas d’échec pour un seul utilisateur.** Mettez plutôt en œuvre une tâche de « finalisation » qui examine toutes les tâches générées et regroupe les enregistrements en échec dans un nouveau fichier. Corrigez les erreurs dans ces enregistrements, puis importez-les dans une nouvelle tâche.

* **Faites preuve de prudence lorsque vous activez le mode `upsert`.** Les importations avec upsert sont plus lentes que les importations standard et ne fusionnent pas les métadonnées. Utilisez le mode upsert lorsque vous devez mettre à jour des utilisateurs existants et que vous comprenez ces limites.
