{"id":1398,"date":"2026-06-10T09:00:00","date_gmt":"2026-06-10T14:00:00","guid":{"rendered":"https:\/\/tolinku.com\/blog\/?p=1398"},"modified":"2026-03-07T03:49:10","modified_gmt":"2026-03-07T08:49:10","slug":"domain-migration-deep-links","status":"publish","type":"post","link":"https:\/\/tolinku.com\/blog\/domain-migration-deep-links\/","title":{"rendered":"Domain Migration for Deep Links: Keeping Links Alive"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Your deep link domain is the foundation of your entire linking infrastructure. Every QR code, email campaign, social post, and ad creative points to it. Changing that domain, or changing where it resolves, is one of the highest-risk operations in a platform migration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This guide covers how to migrate your deep link domain safely: the DNS changes, SSL certificate provisioning, verification file hosting, and redirect strategies that keep existing links working. For the overall migration timeline, see <a href=\"https:\/\/tolinku.com\/blog\/migration-timeline-planning\/\">migration timeline planning<\/a>. For risk mitigation strategies, see <a href=\"https:\/\/tolinku.com\/blog\/migration-risk-mitigation\/\">migration risk mitigation<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Why Domain Migration Is Different<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Changing a deep link platform is not just an API migration. Your domain is embedded in:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>App verification files.<\/strong> Both <a href=\"https:\/\/developer.apple.com\/documentation\/bundleresources\/applinks\" rel=\"nofollow noopener\" target=\"_blank\">Apple&#39;s AASA file<\/a> and <a href=\"https:\/\/developer.android.com\/training\/app-links\/verify-android-applinks\" rel=\"nofollow noopener\" target=\"_blank\">Android&#39;s assetlinks.json<\/a> are hosted on your domain. If these files are not served correctly after the switch, deep links stop opening the app.<\/li>\n<li><strong>Millions of existing links.<\/strong> Links in emails, print materials, QR codes, and social posts cannot be updated after distribution.<\/li>\n<li><strong>DNS caches worldwide.<\/strong> DNS changes propagate gradually. During propagation, some users hit the old server and some hit the new one.<\/li>\n<li><strong>SSL certificates.<\/strong> The new platform must have valid SSL certificates for your domain before it receives traffic.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">A domain migration done poorly results in broken links for hours or days. Done well, users never notice.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Scenario 1: Same Domain, New Platform<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">This is the most common migration path. You keep your existing custom domain (e.g., <code>links.yourapp.com<\/code>) and point it to the new platform&#39;s servers instead of the old platform&#39;s servers.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 1: Configure the Domain on the New Platform<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Before changing any DNS records, set up your domain on the new platform:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Add the domain in the new platform&#39;s dashboard.<\/li>\n<li>Configure all your deep link routes on the new platform.<\/li>\n<li>Verify that the platform is ready to serve your domain&#39;s verification files.<\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">With <a href=\"https:\/\/tolinku.com\/docs\/user-guide\/domains\/custom-domains\/\">Tolinku<\/a>, you add your custom domain in the Appspace settings and configure your routes. Tolinku automatically generates and serves both <code>apple-app-site-association<\/code> and <code>assetlinks.json<\/code> files based on your app configuration.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 2: Pre-Provision SSL Certificates<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">The new platform needs a valid SSL certificate for your domain before it starts receiving traffic. If the platform uses <a href=\"https:\/\/letsencrypt.org\/docs\/\" rel=\"nofollow noopener\" target=\"_blank\">Let&#39;s Encrypt<\/a>, it needs to verify domain ownership first.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Options for certificate provisioning:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>DNS validation (preferred):<\/strong> Add a TXT record for the certificate authority to verify. This works before you change the A\/CNAME records, so the certificate is ready when you switch.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>HTTP validation:<\/strong> Requires the domain to already point to the new platform. This creates a chicken-and-egg problem: you need the certificate before switching, but you need to switch before getting the certificate.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To avoid downtime, use DNS validation or ask the new platform to pre-provision the certificate.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 3: Lower DNS TTL<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">At least 48 hours before the migration, lower your DNS TTL (Time to Live) to 60-300 seconds:<\/p>\n\n\n\n<pre><code>; Before (typical production TTL)\nlinks.yourapp.com.  3600  IN  CNAME  old-platform.example.com.\n\n; 48 hours before migration (lower TTL)\nlinks.yourapp.com.  60    IN  CNAME  old-platform.example.com.\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This ensures that when you make the switch, DNS caches expire quickly. Without this step, some users may see the old DNS records for up to 24 hours after you change them.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Step 4: Switch DNS<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Once the new platform is fully configured, SSL is provisioned, and routes are set up, update your DNS records:<\/p>\n\n\n\n<pre><code>; Migration switch\nlinks.yourapp.com.  60  IN  CNAME  new-platform.example.com.\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 5: Verify After Switch<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Immediately after switching, verify:<\/p>\n\n\n\n<pre><code class=\"language-bash\"># Check DNS resolution\ndig links.yourapp.com\n\n# Check SSL certificate\nopenssl s_client -connect links.yourapp.com:443 -servername links.yourapp.com &lt; \/dev\/null 2&gt;\/dev\/null | openssl x509 -noout -dates\n\n# Check verification files\ncurl -s https:\/\/links.yourapp.com\/.well-known\/apple-app-site-association | python3 -m json.tool\ncurl -s https:\/\/links.yourapp.com\/.well-known\/assetlinks.json | python3 -m json.tool\n\n# Test a deep link\ncurl -sI https:\/\/links.yourapp.com\/your-route\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Step 6: Restore TTL<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">After 24-48 hours of stable operation, restore your DNS TTL to a normal value (3600 seconds or higher):<\/p>\n\n\n\n<pre><code>links.yourapp.com.  3600  IN  CNAME  new-platform.example.com.\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Scenario 2: New Domain<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">If you are changing your deep link domain entirely (e.g., from <code>links.oldname.com<\/code> to <code>links.newname.com<\/code>), you need to handle redirects from the old domain to the new one.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Set Up Permanent Redirects<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Configure your old domain to redirect to the new domain. Use HTTP 301 (permanent) redirects:<\/p>\n\n\n\n<pre><code>Old: https:\/\/links.oldname.com\/promo\/summer\n \u2192 301 redirect to: https:\/\/links.newname.com\/promo\/summer\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The path should be preserved in the redirect. If the route structure differs between platforms, you need a redirect map:<\/p>\n\n\n\n<pre><code class=\"language-javascript\">\/\/ Redirect map for domain migration\nconst redirectMap = {\n  &#39;\/old-campaign-path&#39;: &#39;\/new-campaign-path&#39;,\n  &#39;\/product\/:id&#39;: &#39;\/shop\/:id&#39;,\n};\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Keep the Old Domain Running<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Do not shut down the old domain immediately. Keep it running with redirects for at least 6-12 months. Links in emails, print materials, and cached web pages will continue to reference the old domain long after migration.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Update App Verification for Both Domains<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">If you are running both domains during the transition, both must serve valid verification files:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>links.oldname.com\/.well-known\/apple-app-site-association<\/code> (redirects to new domain)<\/li>\n<li><code>links.newname.com\/.well-known\/apple-app-site-association<\/code> (primary)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">On iOS, Apple follows redirects when fetching the AASA file, so a redirect from the old domain to the new domain works. On Android, the <a href=\"https:\/\/developers.google.com\/digital-asset-links\/v1\/getting-started\" rel=\"nofollow noopener\" target=\"_blank\">Digital Asset Links specification<\/a> requires the file to be served directly (no redirects) at the domain in the intent filter. This means your Android <code>AndroidManifest.xml<\/code> must be updated to reference the new domain.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">App Configuration Changes<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">iOS: Associated Domains<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Update your app&#39;s associated domains entitlement to include both the old and new domains during migration:<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;!-- Associated Domains entitlement --&gt;\n&lt;key&gt;com.apple.developer.associated-domains&lt;\/key&gt;\n&lt;array&gt;\n  &lt;string&gt;applinks:links.newname.com&lt;\/string&gt;\n  &lt;string&gt;applinks:links.oldname.com&lt;\/string&gt;\n&lt;\/array&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">After the migration period (6-12 months), remove the old domain from the entitlement.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Android: Intent Filters<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Add intent filters for both domains during migration:<\/p>\n\n\n\n<pre><code class=\"language-xml\">&lt;intent-filter android:autoVerify=&quot;true&quot;&gt;\n    &lt;action android:name=&quot;android.intent.action.VIEW&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.BROWSABLE&quot; \/&gt;\n    &lt;data android:scheme=&quot;https&quot; android:host=&quot;links.newname.com&quot; \/&gt;\n&lt;\/intent-filter&gt;\n\n&lt;!-- Keep old domain during migration --&gt;\n&lt;intent-filter android:autoVerify=&quot;true&quot;&gt;\n    &lt;action android:name=&quot;android.intent.action.VIEW&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; \/&gt;\n    &lt;category android:name=&quot;android.intent.category.BROWSABLE&quot; \/&gt;\n    &lt;data android:scheme=&quot;https&quot; android:host=&quot;links.oldname.com&quot; \/&gt;\n&lt;\/intent-filter&gt;\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Both domains must serve valid <code>assetlinks.json<\/code> files for Android App Links verification to succeed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Handling the Verification File Gap<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The most dangerous moment in a domain migration is the period between switching DNS and the new platform serving verification files. If there is a gap, even for a few minutes, some devices may cache the failed verification.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">iOS Behavior<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Apple fetches the <code>apple-app-site-association<\/code> file when the app is installed or updated, and caches it for up to 24 hours (via the Apple CDN). If your verification file is unavailable during the DNS switch, newly installed apps or recently updated apps may not open your deep links for up to 24 hours.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">After iOS 14, Apple uses a <a href=\"https:\/\/developer.apple.com\/documentation\/bundleresources\/applinks\" rel=\"nofollow noopener\" target=\"_blank\">CDN-based system<\/a> to fetch and cache AASA files. The CDN updates are not instant.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Android Behavior<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Android re-verifies App Links periodically and when the app is updated. If <code>assetlinks.json<\/code> is unavailable during the switch, Android may fall back to showing a disambiguation dialog instead of opening the app directly.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can force re-verification on a test device:<\/p>\n\n\n\n<pre><code class=\"language-bash\">adb shell pm verify-app-links --re-verify com.yourapp.android\n<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Mitigation: Serve Files from Your Own Infrastructure<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">For maximum control during migration, serve the verification files from your own web server or CDN, independent of the deep linking platform:<\/p>\n\n\n\n<pre><code class=\"language-nginx\"># Nginx: serve verification files directly\nlocation \/.well-known\/apple-app-site-association {\n    alias \/var\/www\/well-known\/aasa.json;\n    default_type application\/json;\n}\n\nlocation \/.well-known\/assetlinks.json {\n    alias \/var\/www\/well-known\/assetlinks.json;\n    default_type application\/json;\n}\n\n# All other requests: proxy to the deep linking platform\nlocation \/ {\n    proxy_pass https:\/\/new-platform.example.com;\n}\n<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This guarantees the verification files are always available, regardless of the platform&#39;s state during migration.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">DNS Propagation and the Split-Brain Problem<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">During DNS propagation, some users resolve your domain to the old platform and some to the new platform. This &quot;split-brain&quot; period typically lasts 1-4 hours with a low TTL, but can extend to 48 hours with high TTLs.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">What Happens During Split-Brain<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Users hitting the old platform: links work as before (old routes, old analytics).<\/li>\n<li>Users hitting the new platform: links work with new routes and new analytics.<\/li>\n<li>New links created on the new platform: only work for users who have the new DNS.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Mitigating Split-Brain Issues<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Keep the old platform running<\/strong> during the propagation window. Do not delete routes or disable the account.<\/li>\n<li><strong>Freeze link creation<\/strong> on the old platform. All new links should be created on the new platform.<\/li>\n<li><strong>Monitor traffic on both platforms<\/strong> during propagation. When traffic on the old platform drops to near zero, propagation is complete.<\/li>\n<li><strong>Use a health check<\/strong> to detect when propagation finishes:<\/li>\n<\/ol>\n\n\n\n<pre><code class=\"language-bash\"># Check from multiple locations (using a service like dig from different regions)\nfor ns in 8.8.8.8 1.1.1.1 208.67.222.222; do\n  echo &quot;Checking via $ns:&quot;\n  dig @$ns links.yourapp.com +short\ndone\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Post-Migration Domain Cleanup<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">After the migration is stable (2-4 weeks), clean up:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Restore DNS TTL<\/strong> to production values (3600+ seconds).<\/li>\n<li><strong>Remove old platform DNS records<\/strong> if you used a separate staging subdomain for testing.<\/li>\n<li><strong>Update documentation<\/strong> with the new platform&#39;s domain configuration.<\/li>\n<li><strong>Notify the old platform<\/strong> that you are done migrating (they may have infrastructure allocated for your domain).<\/li>\n<li><strong>Monitor for 30 days<\/strong> to catch any stragglers or cached DNS entries.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Tolinku Domain Migration<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><a href=\"https:\/\/tolinku.com\/docs\/user-guide\/domains\/custom-domains\/\">Tolinku<\/a> supports custom domains with automatic SSL provisioning via Let&#39;s Encrypt. When you add a custom domain to your Appspace, Tolinku automatically serves the correct <code>apple-app-site-association<\/code> and <code>assetlinks.json<\/code> files based on your iOS and Android app configuration.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For branded link domains, see <a href=\"https:\/\/tolinku.com\/blog\/branded-link-domains\/\">branded link domains<\/a>. For the complete migration process, see <a href=\"https:\/\/tolinku.com\/blog\/migrating-to-tolinku\/\">migrating to Tolinku<\/a>. For redirect strategies during migration, see <a href=\"https:\/\/tolinku.com\/blog\/link-redirect-during-migration\/\">link redirects during migration<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Migrate your deep link domain without breaking existing links. Handle DNS changes, SSL certificates, permanent redirects, and app verification files correctly.<\/p>\n","protected":false},"author":2,"featured_media":1397,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"rank_math_title":"Domain Migration for Deep Links: Keeping Links Alive","rank_math_description":"Migrate your deep link domain without breaking existing links. Handle DNS changes, SSL certificates, and permanent redirects correctly.","rank_math_focus_keyword":"domain migration deep links","rank_math_canonical_url":"","rank_math_facebook_title":"","rank_math_facebook_description":"","rank_math_facebook_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-domain-migration-deep-links.png","rank_math_facebook_image_id":"","rank_math_twitter_title":"","rank_math_twitter_description":"","rank_math_twitter_image":"https:\/\/tolinku.com\/blog\/wp-content\/uploads\/2026\/03\/og-domain-migration-deep-links.png","footnotes":""},"categories":[17],"tags":[254,157,20,168,52,69,88,169],"class_list":["post-1398","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-comparisons","tag-best-practices","tag-custom-domains","tag-deep-linking","tag-dns","tag-migration","tag-mobile-development","tag-redirects","tag-ssl"],"_links":{"self":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1398","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/comments?post=1398"}],"version-history":[{"count":4,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1398\/revisions"}],"predecessor-version":[{"id":2592,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/posts\/1398\/revisions\/2592"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media\/1397"}],"wp:attachment":[{"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/media?parent=1398"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/categories?post=1398"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tolinku.com\/blog\/wp-json\/wp\/v2\/tags?post=1398"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}