As of July 2026, I can confirm this is definitely still an issue.
I have troubleshot a Kinsta → DevKinsta import where the pull/import completed successfully and main.log showed that [wpSearchAndReplace] did run. However, source-environment URLs were still left in live database content afterwards.
The key issue appears to be that the DevKinsta pull/import replacement is too narrow.
In my case, the log showed a replacement like:
https://source-domain.example → http://local-site.local
That completed with exit code 0, so DevKinsta treated it as successful.
However, I found remaining source-domain references in wp_postmeta, specifically inside JSON-style stored data where URLs were escaped, for example:
https:\/\/source-domain.example\/wp-content\/uploads\/...
A plain replacement for:
https://source-domain.example
does not match that raw stored value, because the database value contains escaped slashes.
I confirmed this with SQL on an affected post:
SELECT
LOCATE('https://source-domain.example', meta_value) AS plain_url_match,
LOCATE('https:\\\\/\\\\/source-domain.example', meta_value) AS escaped_url_match,
LOCATE('source-domain.example', meta_value) AS bare_domain_match
FROM wp_postmeta
WHERE post_id = <affected_post_id>
AND meta_key = '<affected_meta_key>';
In my case, plain_url_match was 0, but escaped_url_match and bare_domain_match both returned matches.
The affected data I found was in Elementor-related meta keys such as:
_elementor_data
_elementor_element_cache
But I do not think this is only an Elementor issue. Elementor just makes it easy to see. The broader issue is that any plugin/theme data stored as JSON, escaped strings, encoded content, or serialized data may be missed if DevKinsta only replaces the plain protocol + domain URL.
For comparison, I checked a DevKinsta push back to a Kinsta environment. In that direction, the log showed broader replacements, including:
http://local-site.local → http://destination-domain.example
https://local-site.local → https://destination-domain.example
local-site.local → destination-domain.example
That final bare-domain replacement is important because it catches the domain even inside escaped values such as:
https:\/\/local-site.local\/...
So the issue appears to be specific to the DevKinsta pull/import workflow using a narrower replacement than the push workflow.
In the meantime, the workaround after importing into DevKinsta is to run an additional bare-domain search-replace.
Dry run first:
docker exec -it devkinsta_fpm sh -lc 'cd /www/kinsta/public/local-site-folder && wp --allow-root --skip-plugins --skip-themes search-replace "source-domain.example" "local-site.local" --all-tables --precise --recurse-objects --dry-run'
If that looks correct, run it for real:
docker exec -it devkinsta_fpm sh -lc 'cd /www/kinsta/public/local-site-folder && wp --allow-root --skip-plugins --skip-themes search-replace "source-domain.example" "local-site.local" --all-tables --precise --recurse-objects'
Then verify:
docker exec -it devkinsta_fpm sh -lc 'cd /www/kinsta/public/local-site-folder && wp --allow-root --skip-plugins --skip-themes db search "source-domain.example" --all-tables'
Possible fix: DevKinsta pull/import should run a broader replacement strategy similar to push, including a bare-domain replacement in addition to the protocol-specific URL replacement.