Skip to content

Undici Issues on Appwrite

Published on: June 29, 2024


Undici Issues on Appwrite

Recently, I migrated one of my iOS Apps from a basic PHP server to Appwrite, and overall, the transition was smooth. While I did encounter some minor hiccups with data migration, they were manageable.

However, one particular challenge arose when working with Functions, especially using the Node:20+ Runtime. Consider this snippet of code -

js
// exactly 60 items in here.
for (const [index, randomId] of randomIds.entries()) {
  try {
    const document = await databases.getDocument(
      databaseId,
      collectionId,
      randomId.toString(),
    );

    // perform updates on the document.
    await updateDocument(document, index);
  } catch (error) {
    console.error(`Index: ${index + 1}, Identifier: ${randomId}, ${error}`);
  }
}
If you're wondering why I'm not using something like Promise.all, we'll address that shortly.

In a Node:20+ runtime environment, I often encountered this error:

json
{
  "error": {
    "cause": {
      "code": "ETIMEDOUT"
    }
  }
}

Upon investigating, I learned about recent changes to undici, which handles native fetch operations in Node.js, particularly related to DNS resolution when connecting to domains. While this seemed like a DNS issue, I also considered my Cloudflare setup because I was using an additional domain via CNAME in my Appwrite Project.

Here are the specific test results with Node:20:

  1. Main Domain => Pass
  2. CNAME Domain With Cloudflare Proxy On => Fail
  3. CNAME Domain With Cloudflare Proxy Off => Pass

The solution was either to stick with the main domain assigned to the Appwrite instance or revert to using a Node Runtime version less than 20. Using main domain after assigning a relevant domain wasn't something I wanted, so I just bumped back to using Node:18 & that seems to fix the issue.


Regarding the comment on Promise.all, while it's faster, the timeout issues made it impossible to process updates or fetch documents due to concurrent timeouts. The current logic with the for loop worked, although I had to use delay to avoid the timeouts. However, this approach wasn't effective, and it also significantly increased the processing time for such a small number of documents.


The issue can be tracked here: Appwrite GitHub Issue #8311.

Darshan Pandya