Skip to content
All articles
8 min read

How to Hire a Freelance Developer: 2026 Checklist

MD Rakibul Islam RakibMD Rakibul Islam RakibFull-stack developer, DevOps & Linux engineer
How to Hire a Freelance Developer: 2026 Checklist

To hire a good freelance developer: write a one-page brief, check live work, ask how they'd build it, start with a small paid task, and pay per milestone.

I've been on both sides of this. As a freelancer I get hired, and I'm often hired after another developer: to rescue a half-finished app, recover a server nobody has the password for, or fix a site the previous person stopped answering about. Almost every one of those rescues could have been avoided with a few checks before hiring. This checklist is what I'd tell a friend who's about to hire a developer, including me. It works whether you find people on Upwork, Fiverr, LinkedIn or through a referral.

Key takeaways

  • A clear brief gets you accurate quotes. One page: who the users are, what they must be able to do, what's out of scope, and your deadline.
  • Judge live work, not portfolios of screenshots. Click through real sites and apps the developer built.
  • A small paid trial beats any interview. You learn how they communicate, estimate and deliver.
  • Pay per milestone for working, visible pieces, not for time or promises.
  • You must own the code, domain, hosting and accounts from day one. This is the one rule I'd never bend.

Step 1: Write a one-page brief

Developers quote what they understand. A vague message ("I need an app like Airbnb") gets wildly different prices because each person imagines a different product. A good brief has:

  • The goal: what the business needs, in one sentence. "Customers book and pay for cleaning visits online."
  • The users: who uses it and what each type of user must be able to do.
  • Must-haves vs later: a short list of each. The "later" list matters as much as the first.
  • What exists already: designs, an old site, a database, a domain, brand files.
  • Budget range and deadline: a range is fine. It helps a good developer propose the right-sized solution instead of guessing.

Not sure what a reasonable budget is? I explain how scope drives price in how much a web app MVP costs.

Step 2: Shortlist on evidence

When proposals arrive, look for these signals:

  • They answered your brief. A proposal that mentions your actual users and features beats a copy-pasted list of technologies.
  • Live work you can click. Open the sites. Do they load fast on your phone? Do forms work? Are they still online? A developer who builds things that stay up is worth more than a beautiful screenshot.
  • Relevant experience. If you need payments, ask for an example of a payment integration. If you need a server set up, ask what they run their own projects on.
  • Reviews that mention specifics: "fixed our checkout bug in a day" tells you more than five stars and "great work".
  • Clear writing. Most freelance work happens in messages. If the proposal is hard to follow, the project updates will be too.

Step 3: Ask questions that reveal how they work

Skip trivia questions. Ask about your project:

  1. "How would you build this, and what would you leave out of version one?" A good developer pushes back on scope and suggests simpler options.
  2. "What could go wrong, and what would you need from me?" Look for concrete risks (third-party API limits, content not ready, unclear rules) instead of "nothing, it's easy".
  3. "Where will it be hosted, and what will it cost per month?" They should know, and the answer should be in your name.
  4. "How will I see progress?" Good answers: a staging link updated as work lands, a shared task list, short weekly updates.
  5. "What happens after launch?" Bug-fix period, support plan, documentation, and how you'd hand the project to someone else if needed.

Step 4: Start with a small paid trial

Before committing to a big project, pay for something small and real: fix one bug, build one page, set up the server, or write a technical plan. A few hours of paid work shows you how they estimate, whether they ask good questions, whether they deliver on the day they said, and the quality of what comes back. It's fair to the developer too, because they're paid for their time. If the trial goes badly, you've lost little.

1Paid trialsmall task 2Core featureon staging 3Payments, admintested by you 4Launch+ handover Pay when each piece works, not up front. Your repo, your domain, your hosting from day one.
Milestones turn one big risk into four small ones. You release each payment when that piece is working on a staging link you can test yourself.

Step 5: Agree on scope, milestones and ownership in writing

A short written agreement prevents most disputes. It should cover:

  • Scope: the features included, and a "not included" list.
  • Milestones: what's delivered at each step and what each costs. Each milestone should be something you can see and test, like "login and dashboard working on staging".
  • Revisions and changes: how many rounds of changes are included, and how new requests are priced.
  • Ownership: you own the code and designs once paid. The developer may reuse general knowledge and open-source libraries, but not your private data or business logic.
  • Support: how long bugs are fixed for free after launch, and the cost of ongoing help.

On platforms like Upwork or Fiverr, use their milestone or order system, which holds the payment until you approve the delivery.

Step 6: Keep control of your accounts

This is where the painful rescues come from. Create these accounts yourself, in your company's name, with your email, and invite the developer:

  • Code: a GitHub or GitLab repository you own. Ask for code to be pushed regularly, not handed over at the end.
  • Domain and DNS: registered to you. Never let a developer register your domain in their own account.
  • Hosting: the VPS or cloud account billed to you. The developer gets their own SSH key or user, which you can remove later.
  • Services: Stripe, email provider, Google Search Console, analytics, app stores. Yours, with the developer added as a user.
  • Passwords: shared through a password manager, never in chat messages.

When the project ends, remove the developer's access and rotate any keys they used. It's routine, not an accusation.

Red flags

  • No live work, or examples that are all templates with the logo swapped.
  • A price far below everyone else with no questions asked about your brief.
  • Large up-front payment requested before any work is visible.
  • "I'll host it on my server" with no access for you.
  • Long silences, then big deliveries you can't test.
  • Can't explain in plain words how the app will be secured and backed up. If the project was built with AI tools, ask about the checks in my vibe coding security checklist.

Step 7: Plan the handover from the start

Good projects end with you able to continue without the original developer. Ask for a README that explains how to run, deploy and back up the project, a list of every service and account it depends on, and the environment variables it needs (names and what they're for, not the secret values in the document). If the deploy is automated with something like the GitHub Actions pipeline I use, the next developer can ship on day one.

Frequently asked questions

Where can I find a good freelance developer?

Referrals from people who've hired before are best. Upwork, Fiverr and LinkedIn work well too if you shortlist on live work and specific reviews, then start with a small paid task before the full project.

Should I pay a freelance developer hourly or a fixed price?

Fixed price works best for a well-defined project, because you know the total in advance. Hourly suits ongoing work or unclear problems, such as debugging an unfamiliar codebase. Either way, pay in milestones tied to working results.

How much should I pay up front?

Ideally nothing beyond the first milestone. On platforms, fund one milestone at a time. Off platform, a modest deposit for the first milestone is normal, with the rest paid as each milestone is delivered and tested.

How do I protect my idea when hiring a developer?

Sign a simple agreement covering confidentiality and code ownership, and keep the repository and accounts in your name. In practice, execution matters far more than the idea, and owning your code and accounts is the real protection.

What should I get at the end of a project?

Working software on hosting you own, the full source code in your repository, documentation to run and deploy it, a list of services and accounts, and a short support period for bugs found after launch.

Looking for a developer?

I build web apps and websites with fixed prices, milestones you can test, and everything in your name from day one. Browse my projects, see the MVP package and other web development services, or contact me with your brief. A small paid trial is always welcome.

MD Rakibul Islam Rakib

Written by

MD Rakibul Islam Rakib

Full-stack developer, DevOps engineer and Linux system administrator with 5+ years of production experience. I deploy, harden and fix servers and web apps for clients worldwide, and everything in this article runs on real servers I manage, including this site.

  • hire a freelance developer
  • hiring a web developer
  • freelance developer checklist
  • developer red flags
  • paid trial
  • milestone payments

Keep reading

Cloudflare in Front of Your VPS: Setup Checklist
DevOpsOct 7, 2026

Cloudflare in Front of Your VPS: Setup Checklist

Cloudflare in front of a VPS: use Full (strict) SSL, restore real visitor IPs in Nginx, and firewall the origin so only Cloudflare reaches ports 80 and 443. Cloudflare's free plan gives a small business site a global CDN, DDoS protection and free HTTPS at the edge, and setup looks like "change your nameservers, done". The problems show up later: an endless redirect loop, logs and rate limits that only ever see Cloudflare's IPs, attackers going around Cloudflare straight to the server's IP, or a checkout page cached for everyone. This is the checklist I use when I put a client's VPS behind Cloudflare, with the Nginx and UFW commands for Ubuntu. Key takeaways Use Full (strict), never Flexible. Flexible sends traffic to your server unencrypted and causes redirect loops with an HTTPS redirect on the origin. Give the origin a real certificate: Let's Encrypt or a free Cloudflare Origin CA certificate. Restore the visitor's IP with Nginx's real_ip module and the CF-Connecting-IP header, or fail2ban and rate limits see only Cloudflare. Lock the origin so ports 80 and 443 only accept Cloudflare's IP ranges, and don't leak the server IP through other DNS records. Cache static assets, not personal pages. Never cache HTML for logged-in users, carts or dashboards. 1. Add the site and check every DNS record When you add a domain, Cloudflare scans your existing DNS records. The scan misses things, so compare it against an export from your current DNS provider before switching nameservers: MX, TXT (SPF, DKIM, DMARC, verification records), CNAMEs for subdomains and any CAA records. Missing an MX record breaks your email the moment the nameservers change. Then decide which records are proxied (orange cloud) and which are DNS only (grey cloud): Proxied: the website and app hostnames: example.com , www , app . DNS only: mail servers (MX targets), anything using non-web ports like SSH or a database, and services that must see the client directly. Only HTTP and HTTPS on standard ports (plus a short list of alternates) go through the proxy on the free plan, so an SSH hostname must be grey-clouded. 2. Set SSL/TLS to Full (strict) This setting controls how Cloudflare talks to your server . The visitor always sees HTTPS either way, which is why the wrong choice can go unnoticed. Flexible: Cloudflare connects to your server over plain HTTP. Traffic between Cloudflare and your server is unencrypted, and if Nginx redirects HTTP to HTTPS you get ERR_TOO_MANY_REDIRECTS , because every request arrives as HTTP and gets redirected forever. Full: HTTPS to the origin, but any certificate is accepted, even expired or self-signed ones. Full (strict): HTTPS with a valid certificate checked. This is the one you want. Newer zones may show "Automatic SSL/TLS" instead, where Cloudflare picks the most secure mode your origin supports. That's fine as long as your origin has a valid certificate so it can choose Full (strict). You can check or override it under SSL/TLS → Overview. 3. Give the origin a certificate Two good options: Let's Encrypt with Certbot. The HTTP challenge works through the proxy in most setups. The more robust option is the DNS challenge with the Cloudflare plugin and a scoped API token (Zone → DNS → Edit for this zone only), which also works before DNS points at the server. Cloudflare Origin CA. Generate it under SSL/TLS → Origin Server, with a validity of up to 15 years, and install the certificate and key in Nginx. It's trusted by Cloudflare only, not by browsers, so it breaks if you ever switch a record to DNS only or pause Cloudflare. If renewals start failing later, my Certbot renewal guide covers the Cloudflare-specific causes. 4. Restore real visitor IPs in Nginx Behind the proxy, every request comes from a Cloudflare IP. Your access logs, fail2ban, rate limiting and any "block this IP" rule become useless, or worse, ban Cloudflare. Cloudflare sends the real IP in the CF-Connecting-IP header; Nginx's real IP module can use it, but only for requests from Cloudflare's ranges. Generate the config from Cloudflare's published lists: { for ip in $(curl -s https://www.cloudflare.com/ips-v4) $(curl -s https://www.cloudflare.com/ips-v6); do echo "set_real_ip_from $ip;" done echo "real_ip_header CF-Connecting-IP;" } | sudo tee /etc/nginx/conf.d/cloudflare-realip.conf sudo nginx -t && sudo systemctl reload nginx Reload a page and check the access log shows your own IP. Cloudflare's ranges change rarely, but they do change, so re-run this every few months or from a monthly cron job. Real traffic arrives through Cloudflare with the visitor's IP in a header Nginx can trust. Requests that skip Cloudflare and hit the server's IP directly are dropped by the firewall. 5. Lock the origin to Cloudflare Cloudflare only protects traffic that goes through it. If someone finds your server's IP, they can bypass the CDN, the WAF and DDoS protection completely. Allow web traffic only from Cloudflare's ranges with UFW: for ip in $(curl -s https://www.cloudflare.com/ips-v4) $(curl -s https://www.cloudflare.com/ips-v6); do sudo ufw allow proto tcp from "$ip" to any port 80,443 comment 'cloudflare' done sudo ufw delete allow 'Nginx Full' # or: sudo ufw delete allow 80,443/tcp sudo ufw status numbered Keep your SSH rule in place before changing anything. If any app runs in Docker with published ports, UFW rules don't apply to it; see Docker bypasses UFW . For stronger protection, enable Authenticated Origin Pulls so Nginx only accepts connections that present Cloudflare's client certificate. Also stop leaking the IP: don't point grey-clouded records like mail or ftp at the same server as the website, check that emails sent from the server don't reveal its IP in headers, and remember that old DNS history sites may still show your previous IP. After a serious attack, changing the server IP is sometimes the cleanest fix, and my zero-downtime migration guide shows how. 6. Cache the right things By default Cloudflare caches static files by extension (images, CSS, JS, fonts) and not HTML. That's a safe start. Then: Send good cache headers from your app. Next.js already marks /_next/static/ files as immutable; your own uploads and images should have a long Cache-Control too. Only cache HTML on purpose, with a cache rule for public pages, and bypass it for /admin , /account , /checkout , /api and any request with a session cookie. Purge after deploys if you cache HTML, or use short edge TTLs. Caching a personalised page is the most dangerous Cloudflare mistake: one customer's account page can be served to the next visitor. 7. Know the limits Upload size: the Free and Pro plans accept request bodies up to 100 MB. Larger uploads need a DNS-only hostname, chunked uploads or direct-to-storage uploads. Timeouts: if your server takes longer than about 125 seconds to respond, visitors see error 524. Long jobs should run in the background; my 504 Gateway Timeout guide explains how. WebSockets work through the proxy on all plans, so chat and live features keep working. 8. Turn on the useful free extras Always Use HTTPS and Automatic HTTPS Rewrites (you can then drop your own HTTP→HTTPS redirect, or keep it; with Full (strict) both are fine). HSTS , once you're sure every subdomain works over HTTPS. Bot Fight Mode and a WAF rule to challenge traffic to /wp-login.php or /admin from countries you don't serve. Under Attack mode : know where the switch is before you need it. Cloudflare is one layer. The server behind it still needs the basics in my Ubuntu hardening checklist . Frequently asked questions Why do I get "too many redirects" after enabling Cloudflare? Your SSL/TLS mode is probably Flexible while your server redirects HTTP to HTTPS. Cloudflare connects over HTTP, the server redirects to HTTPS, and the loop repeats. Install a certificate on the server and switch the mode to Full (strict). Should I use Flexible or Full SSL in Cloudflare? Full (strict). Flexible leaves traffic between Cloudflare and your server unencrypted and causes redirect loops. Full without strict accepts invalid certificates, so it protects less than it seems. How do I see real visitor IPs behind Cloudflare? Configure Nginx with set_real_ip_from for each Cloudflare IP range and real_ip_header CF-Connecting-IP , then reload. Logs, fail2ban and rate limits will then see the visitor's IP instead of Cloudflare's. Does Cloudflare hide my server's IP address? Only for proxied records, and only if the IP doesn't leak elsewhere: grey-clouded records on the same server, outgoing email headers, or old DNS history. Restrict ports 80 and 443 to Cloudflare's ranges so a leaked IP is useless. Is Cloudflare's free plan enough for a business website? For most small business sites, yes: CDN, free edge certificates, DDoS protection, basic WAF rules and caching are all included. Paid plans add more WAF features, image optimisation and support. Want Cloudflare and your server set up properly? I set up VPS servers with Nginx, HTTPS, Cloudflare, real-IP logging and a locked-down firewall, and deploy your app on them. See my VPS setup service , the server hardening and security audit , all DevOps services , or contact me with your domain and hosting details.

Read article →
Landing Page That Converts: 11 Things to Get Right
Website DesignOct 7, 2026

Landing Page That Converts: 11 Things to Get Right

A landing page converts when it has one goal, a headline that names the outcome, proof near the button, answers to objections, and loads in under 2.5 seconds. Most landing pages I'm asked to fix don't have a design problem. They have a clarity problem: three different buttons, a headline about the company instead of the customer, testimonials hidden at the bottom, and a hero image so heavy the page takes five seconds to show anything on a phone. Visitors decide fast whether a page is for them. This checklist covers the 11 things I check on every landing page I build or review, in the order a visitor experiences them. Key takeaways One page, one goal, one main button. Every extra choice lowers the chance of the one you want. The headline says what the visitor gets , for whom, in plain words. Your company name can wait. Put proof next to the ask: real reviews, client names, numbers you can back up. Answer objections on the page with a short FAQ: price, time, risk, what happens next. Speed is part of conversion. Aim for a Largest Contentful Paint under 2.5 seconds on mobile, and measure conversions so you know what works. Above the fold: the first five seconds 1. Pick one goal Decide the single action the page exists for: book a call, request a quote, start a trial, buy. Remove the main menu if you can, or at least keep it minimal, and make every button on the page do that one thing. A landing page from an ad with links to your blog, careers page and social profiles is leaking visitors. 2. Write a headline about the outcome Compare "Innovative Cloud Solutions" with "Your website back online in hours, not days." The second tells the visitor what they get. A good formula is outcome + for whom + without the pain : "Bookkeeping for small cafés, done in a day a month." Under it, one sentence explains how. 3. Make the button say what happens "Submit" and "Learn more" are weak. "Get my free quote", "Book a 15-minute call" or "Start fixing my site" set expectations. Show the main button above the fold on mobile, give it the strongest colour on the page, and repeat it after each major section. 4. Show the product or the result A real screenshot, a short demo, a before-and-after or a photo of your actual work beats an abstract illustration. Visitors want to see what they're buying. Size it properly: this image is often the page's Largest Contentful Paint, so it must be compressed and loaded first. Each section answers the next question in a visitor's head, in order. The same single button appears at the top and again at the end, after the objections are answered. Below the fold: earning the click 5. Proof, right where the decision happens Put your strongest proof immediately under the hero and again near the final button: short reviews with real names, client logos (with permission), a project count or rating you can back up, and case results. Specific beats glowing: "Fixed our checkout in a day, sales came back the same evening" persuades more than "Amazing service!". Never invent testimonials or numbers. Besides being dishonest, fake reviews break consumer protection rules in many countries, and visitors can usually tell. 6. Benefits first, features second Three short blocks, each a benefit in the customer's words with the feature that makes it true underneath. "Never lose a booking" (benefit) → "automatic SMS reminders 24 hours before" (feature). 7. Show how it works in three steps People hesitate when the next step is unclear. "1. Tell us about your project. 2. Get a fixed quote within a day. 3. We build it, you approve each milestone." Three steps make the decision feel small. 8. Answer objections with a short FAQ List the questions you hear on sales calls: How much does it cost? How long does it take? What if I'm not happy? Do I need to prepare anything? Answer each in two or three sentences. A FAQ also gives Google and AI answer engines clear question-and-answer text to show, which brings more qualified visitors. 9. Keep the form short Every field you add is a reason to leave. For a first contact, name, email and one open question ("What do you need help with?") is usually enough. Ask for budget, phone and company size later, or make them optional. Show what happens after submitting: "I reply within one working day." Under the hood: speed, mobile and measurement 10. Make it fast on a phone Google treats a Largest Contentful Paint under 2.5 seconds as good, and slow pages lose visitors before they've read the headline. Compress the hero image and load it with high priority, use at most two font families, and drop heavy sliders, chat widgets and tracking scripts you don't use. My guide to fixing a slow LCP walks through each step. Then test on a real phone: tap targets big enough, no text too small, no sideways scrolling, the form easy to fill with a thumb. 11. Measure conversions, then change one thing at a time Track the button clicks and form submissions as conversions (key events in Google Analytics 4, or your ad platform's conversion tracking). Without that, you're redesigning on opinions. Once you have a baseline, test one change at a time, headline first, because it has the biggest effect. Small sites rarely have the traffic for formal A/B tests; changing the headline for two weeks and comparing the conversion rate is still far better than guessing. Website builders or a custom page? Builders like Webflow, Framer and Wix can produce a good landing page if you follow the checklist above, and they're quick to edit. A custom page built in Next.js gives you full control over speed, tracking and integration with your app or CRM. I compared both in AI website builders vs a custom website . If you're replacing an existing site, read how to redesign without losing SEO first. Frequently asked questions What makes a landing page convert? A clear single goal, a headline that states the outcome for a specific visitor, one obvious button, proof near that button, answers to common objections, a short form, and a page that loads quickly on mobile. How long should a landing page be? As long as it takes to answer the visitor's questions. A free download can be short. An expensive service needs more proof and more answers. Keep the main button visible at the top and repeat it after each major section so long pages don't hide it. Should a landing page have a navigation menu? For ad and campaign pages, usually not, or only a minimal one, because every link away from the page is a lost conversion. A service page on your main website can keep the normal menu. How many form fields should a landing page form have? As few as you need to start the conversation, often three: name, email and a short message. Extra qualifying questions can be optional or asked in the follow-up. How do I know if my landing page is working? Track conversions as events in your analytics and divide them by the number of visitors to get a conversion rate. Compare it over time and after each change, rather than judging by how the page looks. Want a landing page built to convert? I design and build fast landing pages with clear copy structure, real proof, conversion tracking and a sub-2.5-second load on mobile. See my landing page design and build service , all website design services , or contact me with your current page and the one action you want visitors to take.

Read article →
Migrate a Website to a New Server With Zero Downtime
DevOpsOct 7, 2026

Migrate a Website to a New Server With Zero Downtime

Move a site to a new server with zero downtime: lower the DNS TTL early, copy and test, do a final data sync, switch DNS and keep the old server running. Server migrations have a bad reputation because the usual approach is "copy everything, change DNS, hope". Then emails stop arriving, uploads from the last hour are missing, the SSL certificate isn't there yet and half the visitors still land on the old server. I move client sites between providers regularly, often to cut hosting costs or get off an old, unpatched machine, and the plan below is how I do it without customers noticing. It works for Node.js, PHP and WordPress sites alike. Key takeaways Lower the DNS TTL to 300 seconds at least a day before the move, so the switch spreads in minutes instead of hours. Inventory everything first: sites, databases, uploads, cron jobs, environment files, email and every DNS record. Test the new server before switching DNS with curl --resolve or your hosts file. Sync data twice: a full copy while the old server is live, then a short final sync during a brief write freeze. Keep the old server running for a week as your rollback plan, and only then cancel it. Step 1: Inventory the old server Most migration problems are things nobody remembered existed. Before touching anything, write down: Sites and apps: ls /etc/nginx/sites-enabled/ (or Apache's), pm2 list , docker ps , systemctl list-units --type=service --state=running . Databases: names, sizes, users and versions. Moving PostgreSQL 14 to 17 or MySQL 5.7 to 8 is an upgrade too; test it. Files: app code, user uploads, generated files, and the .env or config files with secrets. Scheduled jobs: crontab -l for every user, sudo crontab -l , /etc/cron.d/ and systemd timers. DNS: export every record from your DNS provider. Note MX, SPF, DKIM and DMARC records, and any subdomains pointing at the old IP. Email: does the server send mail (contact forms, receipts) directly or through a provider? Does it receive mail? Things that trust the old IP: payment provider webhooks, API allowlists, a database firewall, an SMS gateway, a partner's IP whitelist. Step 2: Lower the DNS TTL The TTL tells resolvers how long to cache your DNS record. If it's 86400 (a day), some visitors keep going to the old server for up to a day after you switch. Change the TTL of the A/AAAA records you'll move to 300 seconds, then wait at least as long as the old TTL before migrating so every cache has picked up the short value. Check what the world sees with: dig +noall +answer www.example.com The number before IN A is the remaining TTL. If you use Cloudflare's proxy (orange cloud), the switch is near-instant anyway, because visitors only ever see Cloudflare's IPs. I cover that setup in the Cloudflare VPS checklist . Step 3: Build and secure the new server Set up the new server properly from the start rather than copying the old one's mistakes: a non-root sudo user, SSH keys only, a firewall, automatic security updates. My Ubuntu 24.04 hardening checklist is the list I follow. Install the same major versions of your runtime (Node, PHP, Python) and database, or plan and test the upgrade. Then set up Nginx and the app the way I describe in deploying Next.js on a VPS with PM2 and Nginx . Step 4: First full copy of files and databases Copy files with rsync over SSH. It preserves permissions and can be re-run later to copy only what changed: rsync -aHAX --info=progress2 \ old-server:/srv/app/shared/uploads/ /srv/app/shared/uploads/ For databases, take a logical dump and restore it on the new server: # PostgreSQL ssh old-server "pg_dump -U app -Fc appdb" > appdb.dump pg_restore -U app -d appdb --no-owner appdb.dump # MySQL / MariaDB ssh old-server "mysqldump --single-transaction appdb" | mysql appdb Copy the .env files and cron jobs, and point the app's config at the new database. Don't enable cron jobs that send emails or charge cards yet, or customers get everything twice. Step 5: Test the new server before anyone sees it You need HTTPS working before the DNS switch, but Let's Encrypt's normal HTTP check needs DNS to already point at the new server. Three ways around it: copy /etc/letsencrypt from the old server, use a DNS-01 challenge with your DNS provider's plugin, or use a Cloudflare Origin CA certificate if you're behind Cloudflare. Then test the real domain against the new IP without changing DNS: curl -sI --resolve www.example.com:443:203.0.113.20 https://www.example.com/ For clicking around in a browser, add 203.0.113.20 www.example.com to your computer's hosts file temporarily. Log in, submit forms, upload a file, run a test payment, check the logs for errors. Remove the hosts entry when you're done. With a short TTL set in advance, changing the A record moves visitors to the new server within minutes. The old server stays up, so anyone still on a cached record is served normally. Step 6: Final sync and the switch The only moment data can be lost is between the last copy and the DNS switch. Keep it short: Pick a quiet time and tell the client or team. Freeze writes on the old server: a maintenance page for logged-in actions, or stop the app's workers, so no new orders or uploads land there. Final sync: re-run the same rsync (fast, only changes) and take a fresh database dump and restore. Switch DNS to the new IP. Enable cron jobs and workers on the new server, and disable them on the old one. Watch both servers' access logs. Traffic on the old one should drop to almost nothing within minutes. For a site where even a few minutes of frozen writes is too much, you can set up database replication from old to new and promote the new one at switch time. It's more work and only worth it for busy stores and apps. Step 7: After the switch Update everything that trusted the old IP: webhooks, allowlists, SPF records if the server sends mail directly. Check email both ways. Send a contact-form test and a real email to the domain. Check renewals: run sudo certbot renew --dry-run on the new server. Set up backups and monitoring on the new server on day one, not "later". Keep the old server for about a week, powered on, as a rollback. Take a final snapshot before cancelling it. Raise the TTL back to an hour or more once everything is stable. Frequently asked questions How long does it take to migrate a website to a new server? Preparing, copying and testing usually takes a few hours to a couple of days, depending on the size of the data and the number of services. The actual switch, with a short TTL and a final sync, takes minutes. Will my website go down during migration? Not if you test the new server first, lower the TTL in advance and keep the old server running. Visitors with cached DNS still reach the old server, which keeps working until their cache expires. How do I get an SSL certificate before changing DNS? Copy the existing Let's Encrypt files from the old server, use a DNS-01 challenge through your DNS provider, or use a Cloudflare Origin CA certificate if your site is behind Cloudflare. The normal HTTP challenge only works after DNS points at the new server. How long does DNS propagation take? As long as the record's TTL. With a TTL of 300 seconds set a day ahead, most visitors move within five to ten minutes. A few badly behaved resolvers cache longer, which is why the old server should stay up for a while. Can I move from shared hosting to a VPS this way? Yes. Download files over SFTP or the host's backup tool, export the database from phpMyAdmin or the control panel, and follow the same test-then-switch steps. Pay special attention to email, which shared hosting often provides and a plain VPS doesn't. Want your site moved for you? I migrate websites and apps between servers and providers, including off Vercel, Heroku and shared hosting, with testing before the switch and the old server kept as a fallback. See my hosting migration service , the VPS setup service , all DevOps services , or contact me with what you're running now and where you want it.

Read article →