For a bigger database (34386 documents), I encounter a performance drop in ftinfex use : a few seconds in 11.9 against 17 minutes with the last release.
Words with a few hits respond quickly but when hits are numerous (here around 4000), it takes many minutes (here 17 minutes).

I guess it would take longer… but probably not much as in your case.

Basically, the enforceindex option is a lax convenience workaround for cases in which the optimizer is not smart enough to rewrite the expression for index access. However, to ensure that the results are correct, and match the input documents, several steps need to be performed that are otherwise done once at compile time. Specifically, an expression like…

  $documents//text()[. contains text 'X']

…is rewritten to something like…

  ft:search('db', 'X')[some $doc in $documents satisfies $doc is ancestor::document-node()]

In your case, it’s probably better to directly use ft:search. There are several approaches how to ensure that the results are contained in specific documents of a database. One approach is to match the database paths of the document and the result nodes:

declare function local:getHit($documents, $word) {
  let $db := db:name(head($documents))
  let $paths := $documents ! db:path(.)
  return ft:search($db, $word)[db:path(.) = $paths]
};

Hope this helps,
Christian