Migrating 50GB of WooCommerce Data from AWS Singapore to Alibaba Cloud Singapore Without a Single Minute of Downtime
Migrating 50GB of WooCommerce Data from AWS Singapore to Alibaba Cloud Singapore Without a Single Minute of Downtime
The decision to migrate came on a Tuesday afternoon, not from a grand strategic review but from a spreadsheet. The AWS bill for the Singapore region had crept past $4,200 a month for a WooCommerce store selling industrial-grade adhesives, a business that operated on thin margins and high inventory turnover. The owner, a man named Darren who ran the operation from a three-desk office in Ubi, had been watching the numbers for six months before he finally called a friend who ran infrastructure at a logistics startup. That friend suggested Alibaba Cloud’s Singapore data center, which offered comparable compute and storage at roughly a third of the cost — but only if the migration went smoothly. One minute of downtime could mean three hundred abandoned carts, which, for a store averaging $40 per order, was not a theoretical loss.
The Corrupt Forty-Three-Minute Dump
The first mistake was thinking the migration would be a straight data transfer. Fifty gigabytes of WooCommerce data — products, customer accounts, order histories, media uploads, plugin databases — sounds manageable. In practice, the bottleneck was never the data itself. It was the database queries running live while the data moved. WooCommerce on a busy store does not sit still. Every second of the migration, customers were adding items to carts, checking stock levels, and placing orders. The MySQL database on the AWS Singapore instance was writing new rows faster than any export tool could keep pace.
Darren’s hosting provider at the time had set up the site on a c5.xlarge instance with a separate RDS database — a reasonable setup for WooCommerce, but one that made snapshots more complicated. The first attempt, on a Wednesday evening, tried using the standard mysqldump command while the site was live. The export took forty-three minutes. The file was corrupt. The second attempt, using the --single-transaction flag, produced a clean export but took an hour and twelve minutes, during which the site remained fully live. The problem was that the export itself locked certain InnoDB tables for long enough that order processing slowed noticeably. Not a crash — just a lag. Customers saw the spinning wheel icon for seven extra seconds at checkout. That was the kind of problem that didn’t show up in monitoring alerts but did show up in the abandonment rate the next morning.
The 3 A.M. Dump and the Almost-Forgotten IAM User
The approach that finally worked involved three separate steps, run in sequence, each with its own failure mode. The first was a full database dump taken during a period of deliberately low traffic — 3 a.m. Singapore time, a Wednesday, when the store typically saw fewer than a dozen active sessions. The dump itself used mysqldump --single-transaction --quick --lock-tables=false, a combination that avoided table locks entirely but required enough memory on the export machine to handle the full dataset in one pass. The AWS instance had 8GB of RAM, which was sufficient. The dump completed in twenty-seven minutes and produced a 4.3GB SQL file.
The second step was the media library. WooCommerce media — product images, PDF spec sheets, category banners — had been stored on an AWS S3 bucket attached to the instance. That was 14.2GB of files, all of which needed to move to Alibaba Cloud’s Object Storage Service (OSS). The initial plan involved using the AWS CLI to sync the bucket directly to OSS via the internet, but the transfer rate over the public internet from Alibaba Cloud’s Singapore data center to AWS’s Singapore region averaged only 3MB per second. At that speed, 14.2GB would have taken nearly ninety minutes, during which any request to the old S3 bucket could fail if a file had already been moved but not yet fully copied to OSS.
The workaround was to use Alibaba Cloud’s import tool, which allows direct pulling from an S3 bucket using temporary credentials. That required setting up an IAM user in AWS with read-only access to the specific bucket, then passing those credentials to the Alibaba Cloud console. The transfer ran at 28MB per second, completing in under nine minutes. The catch was that the IAM user had to be deleted afterward — a step nearly forgotten — because the credentials remained valid in Alibaba Cloud indefinitely. An intern caught it three days later while reviewing security logs.
The 11,000-Row Table in phpMyAdmin
WooCommerce itself is fairly straightforward to migrate. The plugins are not. Darren’s store ran twenty-three active plugins, including a subscription manager, a custom shipping calculator tied to a third-party API, and a caching plugin that had been configured specifically for the AWS instance’s underlying architecture. The caching plugin, W3 Total Cache, had been tuned to use AWS’s ElastiCache Redis endpoint as its caching backend. That endpoint would not exist in Alibaba Cloud.
The migration plan had accounted for this by disabling the caching plugin entirely before the migration started. What it had not accounted for was the subscription manager, which stored its renewal schedules in a separate MySQL table that the standard WooCommerce exporter did not include. That table was discovered only because Darren happened to open phpMyAdmin on the old instance while the dump was running and noticed a table called wp_subscriptions_renewal with 11,000 rows. Without those rows, all active subscriptions would have been orphaned — customers would have received their products but the store would have stopped charging them. The discovery came at 4:17 a.m., after the dump had already finished. The team restarted the export with an additional --include-table flag to capture the missed table. That added another fourteen minutes.
The Script That Caught 312 Orders
The conventional wisdom for zero-downtime migration is to lower the TTL on the DNS records before the move, then change the A record or CNAME when the new environment is ready. That advice assumes the TTL change propagates before the cutover. What it does not account for is that some ISPs and corporate networks cache DNS responses for longer than the TTL, regardless of what the record says. In practice, lowering the TTL on the store’s DNS from 3600 seconds to 60 seconds, then waiting twenty-four hours before the cutover, meant that roughly 90% of traffic would hit the new server within a minute. The remaining 10% — mostly corporate and mobile users on aggressive caching — would still hit the old server for up to an hour.
The solution was to run both environments in parallel for seventy-two hours, with the old AWS instance still accepting orders. The Alibaba Cloud instance handled new traffic from the DNS change; the old instance handled stragglers. Both databases had to be kept in sync during that window, which meant setting up a MySQL replication link from the new Alibaba Cloud database to the old AWS database as a slave. That replication link worked for exactly thirty-five minutes before the latency between the two data centers caused replication lag to exceed five minutes, triggering a fail-safe that shut down the slave connection.
The real fix was simpler: a small Node.js script that ran every thirty seconds on the Alibaba Cloud instance, checking the wp_orders table for new rows written on the AWS instance, then copying them over via a REST API call to the old server’s admin endpoint. It was ugly. It worked. The script caught 312 orders during the seventy-two-hour overlap window, none of which were duplicated or lost.
The Footnote Nobody Read
Two hours before the scheduled cutover, at 1 a.m. on a Thursday, the Alibaba Cloud instance went down. Not the whole server — just the web server process. A log check showed an out-of-memory error triggered by the PHP worker pool. The new instance had been configured with the same php-fpm settings as the old AWS instance: 50 child processes, each with 256MB memory limit. On the AWS instance, that configuration worked because the instance had 8GB of RAM. The Alibaba Cloud equivalent, a 4vCPU instance with 8GB of RAM, technically had the same memory, but the Alibaba Cloud hypervisor reserved 1.5GB for system overhead that AWS did not — a detail the documentation mentioned in a footnote on a page about instance types that nobody on the team had read.
The fix was to reduce the php-fpm pm.max_children setting from 50 to 32 and increase the memory limit per child to 384MB. That brought peak memory usage to roughly 11GB, which the instance handled through its swap allocation. Not ideal — swap is slow — but the store’s traffic pattern, with most orders placed between 10 a.m. and 3 p.m., meant the swap was only touched during the occasional flash sale. For a store selling adhesives, flash sales were rare enough to be acceptable.
The Twenty-Eight Minutes of Silent Failure
A detail that nearly derailed the entire migration was not about the web server or the database at all. The store’s transactional emails — order confirmations, shipping notifications, password reset emails — were routed through AWS’s SES service, which had been configured with verified domains, sending limits, and custom DKIM keys. When the DNS cutover pointed the domain to the new Alibaba Cloud server, the email routing remained pointed at SES. That was fine for the first fifteen minutes, then broke when Alibaba Cloud’s default email handling — which does not use SES — started intercepting certain messages that the WooCommerce plugin tried to send via the local mail() function.
The symptom was silent. Emails appeared to send from the admin dashboard, but they never arrived. A test order placed at 2:14 a.m. generated no confirmation email. A password reset request at 2:17 a.m. returned a success message but the email never hit the inbox. The issue was discovered at 2:22 a.m. when Darren, testing from his phone, realized he had not received the test order’s confirmation. The fix was to configure Alibaba Cloud’s DirectMail service with the same sending domain and DKIM settings, then update the WooCommerce email settings to use the SMTP endpoint for DirectMail instead of the server’s default mail handler. That took twenty-eight minutes. During that window, seventeen orders were placed. None of those customers received confirmation emails. The team sent manual follow-ups from a personal Gmail account the next morning, a solution that felt amateurish but covered the gap.
The 1.2% Bounce Rate Bump
Three weeks after the migration, a review of the server logs revealed that the cutover had not been as clean as it felt. The Alibaba Cloud instance had experienced four brief connection timeouts during the first hour — each lasting less than a second, each caught by the load balancer’s health check, each invisible to users. The database replication script had failed twice during the overlap period, both times because the REST endpoint on the old server returned a 503 error during a brief maintenance window that the AWS hosting provider had scheduled without notifying the team. The script had been written to retry failed requests, so no data was lost, but the retry logic introduced a delay of up to ninety seconds for individual order records.
The most meaningful metric was the bounce rate, which increased by 1.2% in the first week after the migration and returned to baseline by the third week. The team attributed the bump to DNS caching issues and the delayed emails. The hosting cost dropped from $4,200 per month to $1,450 per month on the new Alibaba Cloud instance, including the OSS storage costs and the DirectMail service. The savings covered the migration cost in eight weeks.
The Checklist for Next Time
- Run a full inventory of all database tables before the first export, not just the ones the plugin documentation lists. The subscription manager table was the one that nearly failed because nobody had checked.
- Test the PHP worker pool configuration on the target instance type before the cutover, not after. The memory reservation difference between AWS and Alibaba Cloud was documented but not flagged as important.
- Configure transactional email routing on the target environment before the DNS change, not during it. Twenty-eight minutes of silent email failure was the single longest unplanned outage of the migration.
- Run both environments in parallel for at least forty-eight hours, not the overnight window originally planned. The DNS propagation edge case was minor but real, and the replication script handled it only because it existed.
- Keep a manual backup of the subscription-related tables externally, on a separate server, for the first month. The automated backup schedule on Alibaba Cloud was reliable, but having a fallback outside both environments meant a restore could happen even if both went down simultaneously.
The migration was declared complete on a Friday afternoon, five days after the first export attempt. The old AWS instance was terminated on the following Monday after a final confirmation that no orders had been processed on it during the weekend. The cost savings were real, the downtime was zero, and the spreadsheet that had started the whole process was finally closed. The seventeen missing confirmation emails were a detail the customer accounts could not confirm had caused any actual lost sales, but the team knew those customers existed, even if the data did not show their frustration.