MyDealList · Guides
The Asset Migration Protocol: Moving Tech Stacks Post-Purchase Without SEO Drop
Post-acquisition DevOps blueprint: PostgreSQL logical replication, zero-downtime DNS TTL transitions, redirect preservation, and SEO-safe infrastructure migration for acquired SaaS assets.
You closed on a micro-SaaS running on the seller's Heroku hobby dyno, a shared PostgreSQL instance, and DNS managed from a personal Cloudflare account. Day 14 of ownership is when you migrate SaaS infrastructure to your stack—or when you discover the seller's credit card still pays for production. The Asset Migration Protocol (AMP) is the step-by-step DevOps blueprint acquisition operators use to change hosting, server, and database targets without a traffic cliff, an MRR dip, or a Search Console meltdown. This is not theoretical cloud architecture. It is the same runbook roll-up operators use when they consolidate five acquired assets onto a shared Vercel + Supabase + Cloudflare stack in a single quarter.
Most post-acquisition failures are not product failures—they are migration failures. A botched DNS cutover drops organic traffic 40% for six weeks. A naive pg_dump restore locks tables during peak US hours. A URL structure change without 301 maps burns years of backlink equity. The AMP framework sequences infrastructure moves so that zero-downtime database migration and SEO preservation are first-class constraints, not afterthoughts you patch with a blog post titled “We're experiencing issues.”
Pair this guide with our 90-day operational handover (credential rotation and support continuity), tech stack audit (pre-migration debt scoring), saas security audit before cutover (credential and access review), intellectual property transfer checklist (domain and trademark continuity), and programmatic SEO playbook (URL architecture you must not break). You will get PostgreSQL logical replication commands, DNS TTL transition math, bash automation scripts, redirect-map templates, and checklists you can paste into Notion tonight.
Not legal or financial advice. Database migrations carry data-loss risk. Always test on staging clones. Maintain seller access during contractual transition windows unless counsel advises otherwise.
1. Why Infrastructure Migration Is a Post-Acquisition Priority
Sellers optimize for speed-to-MVP, not buyer portability. By close, you inherit a tangled dependency graph: Stripe webhooks pointed at a seller-owned Vercel project, cron jobs on a personal DigitalOcean droplet, S3 buckets under a Gmail-rooted AWS account, and PostgreSQL credentials embedded in a `.env` file nobody has rotated since launch. Delaying migration creates three compounding risks:
- Vendor lock-in via billing: the seller cancels a card, and production dies at 2 AM
- Security exposure: contractors and ex-cofounders retain cloud console access you cannot audit
- Cost opacity: you cannot right-size hosting until workloads run on accounts you control
The AMP window is Days 15–45 post-close—after credential rotation (Days 1–14) and before major product changes (Days 46+). Moving earlier risks destabilizing support during the ownership announcement. Moving later means every feature ship compounds migration debt.
1.1 Migration archetypes in the micro-acquisition band
| Archetype | Typical source stack | Target stack | Primary risk | Est. downtime budget |
|---|---|---|---|---|
| Lift-and-shift | Heroku + Heroku Postgres | Railway / Render + managed PG | Connection string drift | < 5 minutes |
| Platform modernize | PHP monolith on VPS | Next.js on Vercel + Supabase | URL structure change | Zero (with replication) |
| Database only | Shared PG on seller AWS RDS | Your Neon / Supabase / RDS | Replication lag | Zero |
| DNS + CDN re-home | Seller Cloudflare + origin VPS | Your Cloudflare + new origin | TTL propagation delay | Zero (planned) |
| Full consolidation | Multi-asset heterogeneous | Shared platform + schemas | Cross-tenant data bleed | Per-asset staging |
“If you cannot draw the migration on a whiteboard in under ten minutes, you are not ready to run it in production.” — Standard AMP pre-flight rule
1.2 The AMP success criteria
Define measurable gates before you touch production. Vague goals like “move to our AWS” produce vague outages.
- Availability: 99.9%+ uptime during cutover window (measured by synthetic checks, not gut feel)
- Data integrity: row counts and checksum samples match source within 0.01% post-cutover
- SEO stability: indexed URL count in Search Console ±5% at Day 30 post-migration
- Performance: p95 API latency ≤ 110% of pre-migration baseline for 7 days
- Rollback readiness: documented revert path tested on staging within last 72 hours
2. Phase 0: Pre-Migration Inventory and Freeze
Every AMP run begins with an asset inventory—not a GitHub clone, but a complete map of runtime dependencies. Use this checklist during Week 2 post-close, before announcing any migration window to customers.
2.1 The seven-layer inventory model
| Layer | Capture | Tooling | Owner |
|---|---|---|---|
| DNS | All A/AAAA/CNAME/MX/TXT records | dig, Cloudflare export | Buyer DevOps |
| Compute | Processes, cron, workers, queues | Procfile, systemd, PM2 list | Buyer engineer |
| Database | Engine, version, extensions, size | pg_stat_database, SHOW ALL | Buyer DBA |
| Object storage | Buckets, ACLs, CDN origins | aws s3 ls, rclone | Buyer DevOps |
| Secrets | Env vars, API keys, webhook URLs | 1Password export, Doppler | Buyer (post-rotation) |
| Integrations | Stripe, OAuth apps, ESP, analytics | Manual audit spreadsheet | Buyer + seller (48h) |
| SEO surface | Indexed URLs, sitemaps, canonicals | Screaming Frog, GSC export | Buyer growth |
Inventory export script (DNS + HTTP headers)
#!/usr/bin/env bash
# amp-inventory.sh — run from your ops machine, not production
set -euo pipefail
DOMAIN="${1:?Usage: amp-inventory.sh example.com}"
OUTDIR="amp-inventory-${DOMAIN}-$(date +%Y%m%d)"
mkdir -p "$OUTDIR"
echo "[1/4] DNS records..."
dig +noall +answer "$DOMAIN" ANY > "$OUTDIR/dig-any.txt" 2>&1 || true
dig +noall +answer "www.$DOMAIN" A >> "$OUTDIR/dig-any.txt" 2>&1 || true
echo "[2/4] TLS certificate..."
echo | openssl s_client -connect "${DOMAIN}:443" -servername "$DOMAIN" 2>/dev/null \
| openssl x509 -noout -dates -issuer > "$OUTDIR/tls-cert.txt"
echo "[3/4] HTTP response headers..."
curl -sSI "https://${DOMAIN}/" > "$OUTDIR/headers-root.txt"
curl -sSI "https://${DOMAIN}/robots.txt" > "$OUTDIR/headers-robots.txt"
curl -sSI "https://${DOMAIN}/sitemap.xml" > "$OUTDIR/headers-sitemap.txt"
echo "[4/4] Redirect chain..."
curl -sSIL "http://${DOMAIN}/" > "$OUTDIR/redirect-chain.txt"
echo "Inventory written to $OUTDIR/"2.2 Change freeze rules
Declare a migration freeze 72 hours before cutover. During freeze: no schema migrations, no URL refactors, no dependency major-version bumps, no marketing site redesigns. Hotfixes require explicit AMP lead approval and must be cherry-picked to both source and target branches until cutover completes.
3. PostgreSQL Logical Replication for Zero-Downtime Database Migration
For acquired SaaS assets on PostgreSQL 12+, logical replication is the default AMP database strategy. Unlike pg_dump restore—which requires a write lock or maintenance window—logical replication streams row changes to a target cluster while production keeps serving traffic. This is how you execute a zero-downtime database migration on a live micro-SaaS with paying customers.
3.1 When to use logical replication vs alternatives
| Method | Downtime | Best for | Avoid when |
|---|---|---|---|
| Logical replication | Near-zero | PG→PG, same major version | Heavy DDL during sync |
| pg_dump / pg_restore | Minutes to hours | Small DBs (<2 GB), low traffic | 24/7 B2B SaaS with writes |
| Managed provider clone | Varies | Heroku→Neon, Supabase fork | Cross-cloud egress costs |
| Dual-write application | Zero | Custom ORMs, high complexity | No eng bandwidth for code changes |
3.2 Source cluster preparation
On the source PostgreSQL instance (seller's database), enable logical replication and create a dedicated replication user. Run during a low-traffic window—configuration reload is fast, but mistakes here propagate silently.
-- Source: postgresql.conf (requires restart on some providers)
wal_level = logical
max_replication_slots = 4
max_wal_senders = 4
-- Source: create replication role
CREATE ROLE amp_replicator WITH REPLICATION LOGIN PASSWORD 'use-a-vault-generated-secret';
GRANT CONNECT ON DATABASE production_db TO amp_replicator;
GRANT USAGE ON SCHEMA public TO amp_replicator;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO amp_replicator;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO amp_replicator;
-- Source: publication (PostgreSQL 10+)
CREATE PUBLICATION amp_pub FOR ALL TABLES;
-- Verify
SELECT * FROM pg_publication;
SELECT slot_name, active, restart_lsn FROM pg_replication_slots;3.3 Target cluster subscription and sync monitoring
-- Target: initial schema (use pg_dump --schema-only first)
-- pg_dump -h SOURCE_HOST -U admin -d production_db --schema-only --no-owner \
-- | psql -h TARGET_HOST -U admin -d production_db
-- Target: create subscription
CREATE SUBSCRIPTION amp_sub
CONNECTION 'host=SOURCE_HOST port=5432 dbname=production_db user=amp_replicator password=SECRET sslmode=require'
PUBLICATION amp_pub
WITH (copy_data = true, create_slot = true, slot_name = amp_sub_slot);
-- Monitor replication lag (run every 60s during sync phase)
SELECT subname, received_lsn, latest_end_lsn,
pg_wal_lsn_diff(latest_end_lsn, received_lsn) AS lag_bytes
FROM pg_stat_subscription;
-- Row-count parity check (automate in bash loop)
SELECT 'users' AS tbl, COUNT(*) FROM users
UNION ALL SELECT 'subscriptions', COUNT(*) FROM subscriptions
UNION ALL SELECT 'events', COUNT(*) FROM events;Replication lag acceptance formula
3.4 Cutover sequence (database flip)
The database cutover is a choreographed sequence—not a single command. Execute during your lowest-traffic window (typically Sunday 04:00–06:00 UTC for US-centric B2B SaaS).
- Enable read-only mode on source app (feature flag or maintenance middleware returning 503 for writes only)
- Wait for replication lag → 0 (poll
pg_stat_subscription) ALTER SUBSCRIPTION amp_sub DISABLE; verify final row counts- Update application
DATABASE_URLon target hosting to new cluster - Deploy target app; run smoke tests (login, billing, webhook replay)
- Disable read-only on new stack; monitor error rates for 30 minutes
- After 24h clean logs: drop subscription, drop replication slot on source, snapshot source for rollback retention (7 days)
Bash cutover orchestrator
#!/usr/bin/env bash
# amp-db-cutover.sh — requires psql, curl, and platform CLI (vercel/railway)
set -euo pipefail
TARGET_DB_URL="${TARGET_DB_URL:?}"
HEALTH_URL="${HEALTH_URL:?https://staging.example.com/api/health}"
MAX_LAG_BYTES=1048576 # 1 MB
echo "Waiting for replication lag < ${MAX_LAG_BYTES} bytes..."
while true; do
LAG=$(psql "$TARGET_DB_URL" -tAc \
"SELECT COALESCE(pg_wal_lsn_diff(latest_end_lsn, received_lsn), 0)
FROM pg_stat_subscription LIMIT 1;")
echo " lag_bytes=$LAG"
[[ "$LAG" -lt "$MAX_LAG_BYTES" ]] && break
sleep 5
done
echo "Lag acceptable. Disable subscription..."
psql "$TARGET_DB_URL" -c "ALTER SUBSCRIPTION amp_sub DISABLE;"
echo "Deploy target with new DATABASE_URL (platform-specific step)..."
# vercel env add DATABASE_URL production <<< "$TARGET_DB_URL"
# vercel deploy --prod
echo "Smoke test..."
for i in {1..30}; do
STATUS=$(curl -s -o /dev/null -w '%{http_code}' "$HEALTH_URL")
[[ "$STATUS" == "200" ]] && echo "Health OK" && exit 0
sleep 10
done
echo "FAIL: health check did not pass" >&2
exit 1Never drop the source replication slot until the target has run clean for 24 hours. That slot is your time machine—without it, incremental catch-up after a failed cutover requires a full re-sync.
4. DNS TTL Math and Zero-Downtime Cutover
DNS is the most underestimated layer when you change hosting server infrastructure. Resolvers cache records according to TTL. If you flip an A record while TTL is still 86400 seconds, up to 24 hours of traffic may hit the old origin—a split-brain outage that looks like random 502 errors in customer support tickets.
4.1 The TTL reduction schedule
AMP standard: begin TTL lowering 48–72 hours before cutover. Most micro-SaaS assets arrive with TTL 300–3600 on apex and www records. Normalize everything to 60 seconds during migration week.
| Day | Action | Record TTL | Purpose |
|---|---|---|---|
| T−72h | Lower TTL on apex + www | 300s | Begin cache expiry acceleration |
| T−48h | Lower TTL further | 60s | Maximum resolver refresh rate |
| T−24h | Verify global propagation | 60s | Confirm old TTL aged out |
| T−0 | Flip A/CNAME to new origin | 60s | Cutover event |
| T+24h | Raise TTL to steady state | 3600s | Reduce DNS query load |
TTL propagation time formula
If the seller had TTL 86400 and you skip the reduction phase, schedule cutover only after a full 24-hour wait—not Friday afternoon before a weekend traffic spike.
4.2 Blue-green origin validation before DNS flip
Do not use production DNS as your first test. Point a staging subdomain (e.g., origin-new.example.com) to the new host, validate TLS, run synthetic transactions, then flip the production record. Cloudflare and similar CDNs allow origin overrides per hostname without touching apex DNS until ready.
#!/usr/bin/env bash
# amp-dns-verify.sh — compare old vs new origin before cutover
OLD_IP="${1:?old origin IP}"
NEW_IP="${2:?new origin IP}"
DOMAIN="${3:?domain}"
check_origin() {
local ip="$1" label="$2"
echo "=== $label ($ip) ==="
curl -sSI --resolve "${DOMAIN}:443:${ip}" "https://${DOMAIN}/api/health" \
| head -n 5
curl -sS --resolve "${DOMAIN}:443:${ip}" "https://${DOMAIN}/api/health" \
| jq -e '.status == "ok"' > /dev/null && echo "health: OK" || echo "health: FAIL"
}
check_origin "$OLD_IP" "OLD"
check_origin "$NEW_IP" "NEW"4.3 Email and auxiliary records
Acquired newsletter and content assets often have MX, SPF, DKIM, and DMARC records tied to the seller's ESP. Do not modify MX during app cutover unless email migration is in scope. Document every TXT record—Stripe verification, Google Search Console, domain ownership tokens—before any DNS provider transfer. Losing a GSC verification TXT record delays Search Console data for weeks.
5. Preserving SEO Structures During Platform Shifts
Organic traffic is an acquired asset's silent MRR multiplier. A platform shift from WordPress to Next.js, or from /blog/post-slug to /articles/post-slug, without a redirect map is equivalent to burning 15–40% of top-line traffic over 90 days. SEO preservation is not a marketing task—it is an AMP workstream with engineering ownership.
5.1 Pre-migration SEO baseline capture
- Export all indexed URLs from Google Search Console (Performance → Pages, 16-month range)
- Crawl the live site with Screaming Frog or Sitebulb; export status codes, canonicals, hreflang, and meta robots
- Snapshot top 50 URLs by clicks and impressions— these are your no-touch paths during migration
- Download backlink profile from Ahrefs or GSC Links report; flag URLs with inbound links that must 301, not 404
- Archive current sitemap.xml and robots.txt to version control
5.2 URL mapping and redirect rules
Build a CSV redirect map before writing a line of application code. Every old URL resolves to exactly one new URL with HTTP 301 (permanent), not 302. Chain redirects (A→B→C) dilute PageRank—flatten to A→C.
| Old path | New path | Redirect type | Priority |
|---|---|---|---|
| /blog/* | /articles/* | 301 wildcard | P0 |
| /pricing | /pricing | None (preserve) | P0 |
| /features-old | /features | 301 exact | P1 |
| /wp-content/uploads/* | /assets/* | 301 + CDN | P1 |
Next.js redirect config (preserve link equity)
// next.config.js — load from redirects.csv at build time
const fs = require('fs');
const redirects = fs.readFileSync('./seo/redirects.csv', 'utf8')
.trim().split('\n').slice(1)
.map(line => {
const [source, destination] = line.split(',');
return { source, destination, permanent: true };
});
module.exports = {
async redirects() {
return [
{ source: '/blog/:slug*', destination: '/articles/:slug*', permanent: true },
...redirects,
];
},
};5.3 Structured data and canonical continuity
Platform shifts often break JSON-LD templates. Validate with Google Rich Results Test on your top 20 revenue-adjacent pages before cutover. Canonical tags must self-reference the new URL structure—never point canonicals at the old domain after migration. If the acquired asset uses programmatic SEO pages (see our pSEO guide), export the slug-generation function and verify every indexed slug resolves on the new router.
Post-cutover SEO validation script
#!/usr/bin/env bash
# amp-seo-verify.sh — run after DNS cutover
set -euo pipefail
DOMAIN="${1:?domain}"
URLS_FILE="${2:?file with one path per line}"
FAIL=0
while IFS= read -r path; do
[[ -z "$path" ]] && continue
CODE=$(curl -s -o /dev/null -w '%{http_code}' "https://${DOMAIN}${path}")
if [[ "$CODE" != "200" && "$CODE" != "301" ]]; then
echo "FAIL ${path} → HTTP $CODE"
FAIL=1
else
echo "OK ${path} → HTTP $CODE"
fi
done < "$URLS_FILE"
exit $FAIL5.4 Search Console and sitemap handoff
After cutover, submit the new sitemap in Google Search Console within 24 hours. Use the Change of Address tool only if the domain itself changes—subdomain or path migrations rely on 301 maps, not domain migration tooling. Monitor Coverage report daily for 14 days; spikes in “Excluded by redirect” or “Soft 404” indicate broken templates.
6. Application and Hosting Layer Migration
Database and DNS are half the AMP story. The application layer—build pipelines, environment variables, background workers, and object storage—determines whether your migrate SaaS infrastructure project finishes in one weekend or bleeds into month three.
6.1 Environment variable migration matrix
| Variable class | Migration approach | Rotation required |
|---|---|---|
| DATABASE_URL | Flip at DB cutover | Yes (new credentials) |
| STRIPE_* / billing | Dual webhook verify (see 90-day guide) | Webhook secret yes |
| OAuth client IDs | Re-register app URLs on new domain/host | Redirect URI update |
| S3 / R2 bucket paths | rclone sync pre-cutover | New IAM keys |
| Analytics / pixels | Copy IDs; verify firing in Tag Assistant | Usually no |
6.2 Object storage sync (S3 → R2 / new bucket)
#!/usr/bin/env bash
# amp-s3-sync.sh — run before cutover; re-run with --checksum for delta
set -euo pipefail
rclone sync "s3:old-bucket" "r2:new-bucket" \
--progress \
--transfers 8 \
--checkers 16 \
--s3-no-check-bucket \
--log-file=amp-s3-sync.log
# Verify object counts
echo "Source:" && rclone size "s3:old-bucket"
echo "Target:" && rclone size "r2:new-bucket"6.3 Background jobs and cron
Heroku Scheduler and VPS crontabs do not migrate automatically. Export every scheduled job with its exact command, timezone, and failure notification path. On the target stack, disable jobs until DB cutover completes—then enable in dependency order: (1) email queue, (2) billing reconciliation, (3) analytics aggregation, (4) cleanup tasks.
7. The AMP Runbook Timeline (21 Days)
Below is the standard AMP calendar for a single micro-SaaS asset ($1k–$5k MRR, PostgreSQL backend, Cloudflare DNS, Vercel target). Adjust ±7 days for complexity.
| Day | Phase | Deliverable | Gate |
|---|---|---|---|
| 1–3 | Inventory | Seven-layer audit complete | Seller sign-off on integrations list |
| 4–7 | Staging clone | Target env running on subdomain | Smoke tests pass |
| 8–10 | SEO baseline | Redirect CSV + GSC export | Top 50 URLs mapped |
| 11–14 | DB replication | Subscription active, lag monitored | Row parity ±0.01% |
| 15–17 | TTL reduction | TTL 60s on apex + www | 66+ min propagation verified |
| 18 | Cutover rehearsal | Full dry run on staging | Rollback tested |
| 19 | Production cutover | DB flip + DNS flip + SEO verify | Health OK 30 min |
| 20–21 | Stabilize | Monitor + raise TTL | Error rate baseline |
| 22+ | Decommission | Source infra shutdown | 24h clean logs |
8. Rollback Procedures
Every AMP runbook includes a one-page rollback card printed (yes, printed) at the engineer's desk during cutover night. Decision time-to-rollback must be under 15 minutes from first P0 alert.
| Failure signal | Rollback action | Time budget |
|---|---|---|
| Health check fail post-DB flip | Revert DATABASE_URL; re-enable source writes | 5 min |
| 502 spike after DNS flip | Revert A/CNAME to old origin IP | 2 min (+ TTL wait) |
| Data mismatch detected | Disable target writes; re-sync from source slot | 30–120 min |
| SEO 404 burst (>5% top URLs) | Deploy emergency redirect patch; pause decommission | 15 min |
9. Post-Migration Validation Checklist
Copy this checklist into your ops tracker. Every item must be checked within 72 hours of cutover.
- Synthetic uptime monitor green on /api/health, /login, /pricing for 72 hours
- Stripe webhook delivery success rate ≥ 99% in dashboard (last 24h)
- PostgreSQL connection pool utilization < 70% at peak hour
- Search Console: no new Coverage errors on top 50 URLs
- Email deliverability test (SPF/DKIM pass on transactional send)
- Cron jobs executed on schedule (check logs for missed runs)
- Object storage: random sample of 100 files accessible via CDN URL
- Error tracking (Sentry/Bugsnag): no new recurring issues vs baseline
- Seller credentials revoked on source cloud accounts
- Source infrastructure decommission scheduled (not deleted until Day 30)
10. Cost and Complexity Budgeting
Budget migration as a line item in your post-acquisition reserve—not as surprise opex. Typical micro-SaaS AMP costs in 2026:
Under-budgeting migration is how $35k acquisitions become $42k all-in before you ship a single growth experiment. Include AMP labor in your valuation model as post-close capex.
11. Frequently Asked Questions
Can I migrate SaaS infrastructure without taking the site offline?
Yes—for PostgreSQL-backed apps, logical replication plus DNS TTL management achieves near-zero downtime. Static sites and serverless frontends are even simpler: pre-deploy to the new host, validate via staging subdomain, then flip DNS. The only common exception is apps with heavy DDL during migration (adding columns with defaults on 100M-row tables)—schedule those separately.
How long does SEO recovery take after a botched URL migration?
With proper 301 maps, most assets stabilize within 2–4 weeks. Without redirects, recovery takes 8–16 weeks and may never fully restore long-tail rankings. Always run amp-seo-verify.sh on your top URLs before declaring cutover complete.
Should I migrate before or after the seller transition period ends?
Complete inventory and staging during the seller transition window (Days 1–30 per our micro-acquisition playbook). Execute production cutover when you control credentials and the seller is available for 48-hour consultation—not on their last day of contractual support.
What if the acquired app uses MySQL, not PostgreSQL?
MySQL 8.0+ supports similar binlog-based replication for zero-downtime moves. Managed services (PlanetScale, RDS cross-region read replicas) offer provider-native migration paths. The AMP sequencing—inventory, replicate, cutover, SEO verify—remains identical; swap the replication commands for your engine.
Do I need to notify customers before infrastructure migration?
For zero-downtime migrations, a post-cutover email is sufficient: “We upgraded infrastructure for reliability—no action required.” If your cutover window risks brief write unavailability (maintenance mode), notify 72 hours ahead per your customer communication protocol.
Comments from Pro members
Selected feedback from verified Pro subscribers. Timestamps update while you read.
- Jordan K.…
Switched to Pro mainly for the extra analyses and Reddit/X coverage. This workflow section matches how I screen listings now—saves me hours every week.
Pro
- Priya S.…
The cross-marketplace point is huge. I used to miss duplicates across sites. Premium paid for itself after one decent lead I would have skipped.
Pro
- Marcus T.…
As a Pro user I appreciate the emphasis on red flags before diligence. If you are still on Free, at least read the checklist twice before you wire funds.
Pro
- Elena R.…
I send founders here when they ask how I find sub-$10k deals. The internal link to pricing is honest—you really do need Premium or Pro if you are serious.
Pro
- Chris V.…
MyDealList + a simple spreadsheet is my stack for 2026. Dynamic feed + alerts beats refreshing five marketplaces manually. Worth upgrading from Premium to Pro if you scale volume.
Pro
Leave a Reply
Your email address will not be published.