There is no problem not worth solving, and no technology not worth learning!

EdgeOne Traffic Cost Troubleshooting: Moving WordPress Uploads Static Assets to a Cloudflare Media Subdomain

[图2,EdgeOne 昨日 L7 访问流量,显示 6.56 GB]

作者:

,

WordPress CDN & Global Acceleration Practice

图16:浏览器访问正常,网站全球访问成功

(1) Complete migration combat record from Alibaba Cloud DNS to Cloudflare global acceleration

这一套规则遵循 Cloudflare + WordPress 标准 CDN 架构:

(2) CloudFlare SSL/TLS and Cache Rules configuration combat

图12:评论实时生效

(3) WordPress + CloudFlare Recommended Configuration with Cache Rules Practical Optimization (SSL/API/Cached Closed Loop Full Record)

CDN上线后的boce数据

(4) Performance comparison before and after CDN launch: WordPress cache misjudgment correction and real acceleration effect verification

【图9:boce 测试 cn-test,灰云直连阿里云 ECS,平均响应 0.478s】

(5) Is Cloudflare Free Suitable for a Mainland China WordPress Site? A Real-World Test from Cache HIT to Gray-Cloud Direct Aliyun ECS

[Figure 1: Tencent Cloud EdgeOne product page, selecting “Start Now”]

(6) Migrating a WordPress Main Site from Cloudflare Free to Tencent Cloud EdgeOne: A Real-World CDN Acceleration Setup for China and Overseas Traffic

【图2:EdgeOne 上线后 boce 第二次测试,平均响应 0.354s,不可访问 2 个】

(7) How Much Faster Is EdgeOne After Migrating from Cloudflare Free? A Three-Stage WordPress CDN Test with boce and WebPageTest

[图2,EdgeOne 昨日 L7 访问流量,显示 6.56 GB]

(8) EdgeOne Traffic Cost Troubleshooting: Moving WordPress Uploads Static Assets to a Cloudflare Media Subdomain

【图3,EdgeOne 301 请求的 URL Path 排行,集中在 /wp-content/uploads/ 图片路径】

(9) Troubleshooting Persistent EdgeOne 301 Requests After Moving WordPress Images to a Media Subdomain

Recently, I noticed a fairly obvious issue in the Tencent Cloud EdgeOne console: not long after my site was connected to EdgeOne, the secure acceleration traffic included in my plan was being consumed much faster than expected.

I am currently using the EdgeOne Personal plan, which includes 50 GB of secure acceleration traffic. When I checked the usage, 16.55 GB out of 50 GB had already been used. At that pace, the plan probably would not last a full month.

So instead of blindly upgrading to a higher plan, I first analyzed where the traffic was going. Then I moved the WordPress /wp-content/uploads/ static assets to a separate media.shuijingwanwq.com subdomain and let Cloudflare handle that part of the media traffic.

This article records the full troubleshooting and adjustment process.

[Figure 1: EdgeOne plan management page showing secure acceleration traffic usage at 16.55 GB / 50 GB]
[Figure 1: EdgeOne plan management page showing secure acceleration traffic usage at 16.55 GB / 50 GB]

1. First, confirm the EdgeOne traffic usage

I first opened the EdgeOne plan management page to check the current usage.

The numbers I saw were roughly as follows:

Plaintext
安全加速流量:16.55 GB / 50 GB
安全加速请求:33.71 万次 / 300 万次

Those numbers were enough to make me cautious. If the site was consuming around 5 GB per day, the 50 GB quota would be used up very quickly.

Next, I opened the EdgeOne analytics page and checked the L7 access traffic for yesterday and today.

Yesterday’s data looked roughly like this:

Plaintext
L7 访问流量:6.56 GB
EdgeOne 响应流量:6.41 GB
客户端请求流量:145.83 MB
L7 访问请求数:18.32 万次

By country and region, mainland China and the United States were the main sources:

Plaintext
中国大陆境内:3.57 GB
美国:2.22 GB
[Figure 2: EdgeOne L7 access traffic for yesterday, showing 6.56 GB]
[Figure 2: EdgeOne L7 access traffic for yesterday, showing 6.56 GB]

At this point, I could make one preliminary judgment: this did not look like an obvious single-IP attack. In the IP ranking, the top IPs did not account for a very high share, and no single IP was consuming a dominant amount of traffic.

2. Then check the cache status: the MISS ratio was too high

I then switched to the cache status dimension to inspect the data.

Yesterday’s cache status was roughly:

Plaintext
MISS:4.31 GB
HIT:2.03 GB
dynamic:70.72 MB

The cache status this morning looked similar:

Plaintext
MISS:1.15 GB
HIT:514.4 MB
dynamic:10.59 MB
[Figure 3: EdgeOne cache status analysis showing 4.31 GB MISS and 2.03 GB HIT]
[Figure 3: EdgeOne cache status analysis showing 4.31 GB MISS and 2.03 GB HIT]

This showed that the EdgeOne cache hit rate was not ideal. A large amount of traffic was still in MISS status.

However, there is an important detail here: improving the HIT rate does not necessarily reduce the EdgeOne plan traffic directly. Even if a resource is served from an EdgeOne node as a HIT, EdgeOne still consumes secure acceleration traffic as long as it returns that resource to the user.

That is why the real optimization direction was not simply to improve EdgeOne caching. Instead, I moved the high-traffic /wp-content/uploads/ media assets to a Cloudflare-backed subdomain, so EdgeOne would no longer directly carry the transfer of those images and attachments.

3. Finding the real traffic source: the uploads directory and logo.png

In the URL Path ranking, I found one very obvious resource:

Plaintext
/wp-content/uploads/2026/05/logo.png  530.22 MB

By this morning, this file had already consumed:

Plaintext
/wp-content/uploads/2026/05/logo.png  143.07 MB
[Figure 4: URL Path ranking showing logo.png consumed 530.22 MB yesterday]
[Figure 4: URL Path ranking showing logo.png consumed 530.22 MB yesterday]

This logo.png was originally used as both the Site Logo and the site icon. Its dimensions were:

Plaintext
1024 × 1024

The file size was:

Plaintext
884 KB

Because it appears on many pages as the Site Logo, an oversized logo can easily become a high-frequency traffic sink.

So I first resized this image in the WordPress admin area to:

Plaintext
512 × 512

After compression, its size became:

Plaintext
173 KB

That means it dropped from 884 KB to 173 KB, reducing the size of this single file by about 80%.

[Figure 5: WordPress Site Identity page, where the Site Logo and site icon use the same image]
[Figure 5: WordPress Site Identity page, where the Site Logo and site icon use the same image]
[Figure 6: WordPress image editor, resizing 1024×1024 to 512×512]
[Figure 6: WordPress image editor, resizing 1024×1024 to 512×512]

Compressing the logo was necessary, but it only reduced the size of one resource. It did not solve the EdgeOne traffic consumption problem at the root.

That is because /wp-content/uploads/ contains far more than the logo. It also stores many article screenshots, images, ZIP attachments, and other uploaded assets.

4. Confirm that the uploads directory contains more than images

On the server, I checked the largest files under the uploads directory:

Bash
find /data/wwwroot/www.shuijingwanwq.com/wp-content/uploads -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" -o -iname "*.gif" -o -iname "*.pdf" -o -iname "*.zip" \) -printf '%s %p\n' | sort -nr | head -n 10

The result showed that the uploads directory contained quite a few large files, for example:

Plaintext
113223692 /data/wwwroot/www.shuijingwanwq.com/wp-content/uploads/2026/05/com.termux_1002.zip
49688068  /data/wwwroot/www.shuijingwanwq.com/wp-content/uploads/2026/05/FlClash-0.8.93-android-arm64-v8a.zip
7639822   /data/wwwroot/www.shuijingwanwq.com/wp-content/uploads/2026/04/com.wireguard.android-1.0.20260315.zip
6456103   /data/wwwroot/www.shuijingwanwq.com/wp-content/uploads/2025/02/3-1.jpg

This means /wp-content/uploads/ should not be treated simply as an image directory. It is essentially the WordPress media library directory, and it may contain images, compressed archives, PDFs, attachments, and many other uploaded files.

So I did not use img.shuijingwanwq.com. Instead, I chose a more suitable subdomain:

Plaintext
media.shuijingwanwq.com

This name is more appropriate for handling the entire WordPress media library.

5. Create the media subdomain and let Cloudflare handle the traffic

I first added a DNS record in Cloudflare DNS:

Plaintext
类型:A
名称:media
IPv4 地址:源站服务器 IP
代理状态:已代理,也就是橙色云朵开启
TTL:自动
[Figure 7: Adding the media.shuijingwanwq.com record in Cloudflare DNS]
[Figure 7: Adding the media.shuijingwanwq.com record in Cloudflare DNS]

The goal of this step was to make:

Plaintext
media.shuijingwanwq.com

go through Cloudflare instead of EdgeOne.

6. Use OneinStack to add the media virtual host

My server runs on a OneinStack environment, so I directly used:

Bash
~/oneinstack/vhost.sh

to add the virtual host.

The key settings were as follows:

Plaintext
域名:media.shuijingwanwq.com
网站目录:/data/wwwroot/www.shuijingwanwq.com/wp-content/uploads
SSL:Let's Encrypt
HTTP 自动跳转 HTTPS:开启
Rewrite:不启用
Hotlink Protection:不启用
[Figure 8: Successfully adding the media.shuijingwanwq.com virtual host with OneinStack]
[Figure 8: Successfully adding the media.shuijingwanwq.com virtual host with OneinStack]

There is one key point here: the document root of media.shuijingwanwq.com is not the WordPress root directory. It points directly to the uploads directory:

Plaintext
/data/wwwroot/www.shuijingwanwq.com/wp-content/uploads

In this way, an original resource like:

Plaintext
https://www.shuijingwanwq.com/wp-content/uploads/2026/05/logo-e1783470913383.png

can be accessed through the new media domain as:

Plaintext
https://media.shuijingwanwq.com/2026/05/logo-e1783470913383.png

The URL is shorter and better aligned with the purpose of a media asset subdomain.

7. The media virtual host must not execute PHP

The Nginx virtual host configuration generated by OneinStack may include PHP execution rules by default.

However, the root directory of media.shuijingwanwq.com is uploads. The uploads directory should only serve static assets and must not execute PHP.

So I modified:

Plaintext
/usr/local/nginx/conf/vhost/media.shuijingwanwq.com.conf

I changed:

Nginx
index index.html index.htm index.php;

to:

Nginx
index index.html index.htm;

Then I changed the PHP handling rule to return 403 directly:

Nginx
location ~ [^/]\.php(/|$) {
    return 403;
}

Then I tested the configuration and reloaded Nginx:

Bash
nginx -t && nginx -s reload
[Figure 9: media virtual host configuration with PHP execution disabled]
[Figure 9: media virtual host configuration with PHP execution disabled]

After that, I tested:

Bash
curl -I https://media.shuijingwanwq.com/test.php

It returned:

Plaintext
HTTP/2 403
server: cloudflare
cf-cache-status: BYPASS

This confirmed that the media subdomain would not execute PHP, which is very important.

8. Verify whether media assets can be cached by Cloudflare

I first tested the logo:

Bash
curl -I https://media.shuijingwanwq.com/2026/05/logo-e1783470913383.png

The first request may return:

Plaintext
cf-cache-status: MISS

After requesting it again, it became:

Plaintext
cf-cache-status: HIT

In the response headers, I could see:

Plaintext
server: cloudflare
content-type: image/png
content-length: 172972
cache-control: max-age=2592000
cf-cache-status: HIT

Then I tested a relatively large ZIP file:

Bash
curl -I https://media.shuijingwanwq.com/2026/05/com.termux_1002.zip

After the second request, I could also see:

Plaintext
cf-cache-status: HIT
content-length: 113223692

This shows that Cloudflare can properly handle images and large attachments under the media subdomain.

9. Change the WordPress upload asset URL

Next, I needed WordPress itself to output media.shuijingwanwq.com instead of continuing to output:

Plaintext
https://www.shuijingwanwq.com/wp-content/uploads

My server did not have wp-cli installed, so I used PHP to directly load the WordPress environment and check the setting:

Bash
cd /data/wwwroot/www.shuijingwanwq.com && php -r 'require "wp-load.php"; echo get_option("upload_url_path") . PHP_EOL;'

The result was empty, which means the upload URL had not been set separately before.

Then I ran:

Bash
cd /data/wwwroot/www.shuijingwanwq.com && php -r 'require "wp-load.php"; update_option("upload_url_path", "https://media.shuijingwanwq.com"); echo get_option("upload_url_path") . PHP_EOL;'

The output was:

Plaintext
https://media.shuijingwanwq.com
[Figure 10: Using PHP to set WordPress upload_url_path to the media domain]
[Figure 10: Using PHP to set WordPress upload_url_path to the media domain]

Then I continued verifying the internal WordPress upload directory:

Bash
cd /data/wwwroot/www.shuijingwanwq.com && php -r 'require "wp-load.php"; $u = wp_upload_dir(); echo $u["baseurl"] . PHP_EOL;'

The output was:

Plaintext
https://media.shuijingwanwq.com

This confirmed that the internal WordPress upload URL had been switched successfully.

10. Clear the W3 Total Cache page cache

After setting the WordPress upload URL, the frontend pages may not change immediately, because the page HTML may still be cached by W3 Total Cache or EdgeOne.

I first bypassed the cache for testing:

Bash
curl -s 'https://www.shuijingwanwq.com/?media_test=1' | grep -oE 'https://media\.shuijingwanwq\.com/[^"]+|/wp-content/uploads/[^"]+'

At this point, I could see that the page was already outputting:

Plaintext
https://media.shuijingwanwq.com/2026/05/logo-150x150.png
https://media.shuijingwanwq.com/2026/07/1-20-245x300.png
https://media.shuijingwanwq.com/2026/07/2-18-300x230.png
...

This showed that the dynamic WordPress output was already using the media domain.

Then I cleared W3 Total Cache in the WordPress admin area:

Plaintext
Performance → Purge All Caches

I tested the homepage again:

Bash
curl -s https://www.shuijingwanwq.com/ | grep -oE 'https://media\.shuijingwanwq\.com/[^"]+|/wp-content/uploads/[^"]+'

The results had all changed to:

Plaintext
https://media.shuijingwanwq.com/...
[Figure 11: Image URLs in the homepage source have been switched to media.shuijingwanwq.com]
[Figure 11: Image URLs in the homepage source have been switched to media.shuijingwanwq.com]

11. Add a full uploads 301 redirect in EdgeOne

Although the new WordPress output had already switched to the media domain, old URLs might still be visited from historical cached pages, search engines, external references, and older articles:

Plaintext
https://www.shuijingwanwq.com/wp-content/uploads/2026/07/1-20-245x300.png

Without handling this, those old addresses could still go through EdgeOne.

So I added a full uploads 301 redirect rule in the EdgeOne rule engine.

Rule name:

Plaintext
全量 uploads 301

Match condition:

Plaintext
URL path 正则匹配:
^/wp-content/uploads/(.*)$

Action:

Plaintext
访问 URL 重定向
目标请求协议:HTTPS
目标 Hostname:media.shuijingwanwq.com
目标路径:正则替换
正则表达式:^/wp-content/uploads/(.*)$
替换为:/$1
携带查询参数:开启
状态码:301
[Figure 12: EdgeOne full uploads 301 redirect rule configuration]
[Figure 12: EdgeOne full uploads 301 redirect rule configuration]

This rule changes:

Plaintext
https://www.shuijingwanwq.com/wp-content/uploads/2026/07/1-20-245x300.png

into:

Plaintext
https://media.shuijingwanwq.com/2026/07/1-20-245x300.png

Note that I did not delete the long-term static asset cache rule for now. I kept it as a fallback. Because EdgeOne rule deployment can take a while, there was no need to trigger another deployment just to remove a harmless cache rule at this stage.

[Figure 13: EdgeOne rule list showing the Full uploads 301 rule enabled]
[Figure 13: EdgeOne rule list showing the Full uploads 301 rule enabled]

12. Verify whether old URLs redirect to media

Finally, I verified an old URL:

Bash
curl -I https://www.shuijingwanwq.com/wp-content/uploads/2026/07/1-20-245x300.png

It returned:

Plaintext
HTTP/2 301
location: https://media.shuijingwanwq.com/2026/07/1-20-245x300.png
server: TencentEdgeOne
x-cache-lookup: Return Directly

Then I followed the redirect to verify the full chain:

Bash
curl -IL https://www.shuijingwanwq.com/wp-content/uploads/2026/07/1-20-245x300.png

The first part showed EdgeOne returning 301:

Plaintext
HTTP/2 301
location: https://media.shuijingwanwq.com/2026/07/1-20-245x300.png
server: TencentEdgeOne

The second part showed Cloudflare returning the resource:

Plaintext
HTTP/2 200
server: cloudflare
content-type: image/png
content-length: 21891
cf-cache-status: HIT
cache-control: max-age=2592000
[Figure 14: Using curl -IL to verify that an old uploads URL first receives an EdgeOne 301, then Cloudflare returns 200 HIT]
[Figure 14: Using curl -IL to verify that an old uploads URL first receives an EdgeOne 301, then Cloudflare returns 200 HIT]

This confirmed that the full chain was working:

Plaintext
旧地址:www + /wp-content/uploads/...
→ EdgeOne 301
→ media.shuijingwanwq.com
→ Cloudflare 200
→ cf-cache-status: HIT

13. The structure after this optimization

Before the adjustment:

Plaintext
www.shuijingwanwq.com
└── /wp-content/uploads/
    └── 图片、ZIP、附件等资源全部由 EdgeOne 承接

After the adjustment:

Plaintext
www.shuijingwanwq.com
└── HTML 页面仍然走 EdgeOne

media.shuijingwanwq.com
└── WordPress uploads 静态资源走 Cloudflare

Fallback for old URLs:

Plaintext
www.shuijingwanwq.com/wp-content/uploads/*
→ 301
→ media.shuijingwanwq.com/*

With this structure, EdgeOne mainly handles the main site pages, rules, HTML caching, and security protection. Large assets such as images, screenshots, and ZIP attachments are handled by the Cloudflare-backed media subdomain.

14. Why I did not move the entire site back to Cloudflare

This time, I only moved the WordPress /wp-content/uploads/ uploaded assets to Cloudflare. I did not move the entire main site back to Cloudflare.

The reason is that I had already tested running the full www.shuijingwanwq.com site through Cloudflare. The access experience from mainland China was not stable, especially on China Mobile and China Unicom networks, where page loading could be slow. This was one of the main reasons I later moved from Cloudflare to EdgeOne.

So the idea this time was not to “go back to Cloudflare”, but to make a practical split:

Plaintext
HTML 页面、主站访问、WordPress 动态页面:
继续走 EdgeOne

图片、截图、ZIP、PDF 等上传资源:
迁移到 media.shuijingwanwq.com,通过 Cloudflare 承接

The risk of this approach is relatively controllable. My WordPress site already has image lazy loading enabled, so pages do not load all images at once. The first thing users request is still the main site HTML, and those pages continue to be served by EdgeOne.

In other words, when users in mainland China open an article, the initial viewport experience still mainly depends on EdgeOne and the origin cache. Only when users scroll to an image does the browser request the image from media.shuijingwanwq.com.

The expected result is:

Plaintext
主站首屏速度:尽量保持 EdgeOne 的国内访问优势
图片和附件流量:转移到 Cloudflare,降低 EdgeOne 套餐消耗

Of course, this is not a perfect solution. When users in mainland China load article images, the experience may still be affected by Cloudflare’s network quality across different ISPs. But compared with moving the entire site back to Cloudflare, the impact is much smaller because image lazy loading softens it, making the trade-off easier to accept.

So the goal of this optimization was not simply to chase the fastest possible loading speed. It was about balancing the following three things:

Plaintext
EdgeOne 成本
中国大陆用户访问体验
WordPress 媒体资源流量压力

For now, splitting uploads media assets to Cloudflare looks like a safer middle-ground solution than moving the entire site.

15. A few lessons learned

First, do not upgrade the EdgeOne plan immediately just because traffic usage rises.
If I had upgraded directly to a higher plan this time, the cost would have increased noticeably. But after troubleshooting, I found that the main issue was concentrated in the /wp-content/uploads/ static assets, which could be optimized through an architectural adjustment.

Second, a high share of Referer missing does not necessarily mean hotlinking.
In the EdgeOne data, traffic with a missing Referer accounted for a high share. But this can come from browser privacy policies, direct visits, crawlers, in-app browsers, and other normal scenarios. Blocking empty Referers directly can easily hurt legitimate users.

Third, the Site Logo should not use an oversized image.
The original logo was 1024×1024 and 884 KB. It was used as both the Site Logo and the site icon. After compressing it to 512×512, the size dropped to 173 KB. This is still not the most aggressive optimization possible, but it already reduced the traffic consumed by this single resource significantly.

Fourth, the WordPress uploads directory is not only for images.
It may contain images, ZIP files, PDFs, attachments, and many other media assets. That is why media.shuijingwanwq.com is a better name than img.shuijingwanwq.com.

Fifth, the media subdomain must not execute PHP.
The uploads directory should only serve static assets. If the media virtual host allows PHP execution, any abnormal PHP file that enters uploads could become a security risk.

Sixth, avoid changing EdgeOne rules too frequently.
EdgeOne rule deployment may take some time, so I tried to minimize further rule changes. After the full 301 redirect became effective, I kept the long-term static asset cache rule as a fallback for now instead of rushing to delete it.

16. What to monitor next

After completing this migration, I will continue watching the following EdgeOne analytics metrics:

Plaintext
L7 访问流量
URL Path 排行
/wp-content/uploads/ 是否还出现在高流量排名
状态码 301 占比
EdgeOne 套餐用量增长速度

Ideally, the traffic for EdgeOne /wp-content/uploads/ resources should drop significantly. Even if old URLs are still visited, EdgeOne will only return a small 301 response instead of directly transferring the image or ZIP file itself.

This optimization is a fairly practical compromise: I did not fully migrate the CDN, and I did not continue upgrading the EdgeOne plan. Instead, I split out the most traffic-heavy WordPress media assets, allowing EdgeOne and Cloudflare to each handle the parts they are better suited for.

How Much Faster Is EdgeOne After Migrating from Cloudflare Free? A Three-Stage WordPress CDN Test with boce and WebPageTest Troubleshooting Persistent EdgeOne 301 Requests After Moving WordPress Images to a Media Subdomain

Linux Server Operations, Deployment & Production Troubleshooting

If your website or backend service runs on a Linux server and you are facing unstable access, Nginx configuration issues, MySQL / Redis errors, Docker service failures, full disk usage, or high CPU / memory usage, feel free to contact me for remote troubleshooting.

Ideal For:
✅ Website downtime or unstable access
✅ Nginx / PHP-FPM configuration issues
✅ MySQL / Redis performance or connection problems
✅ Docker service deployment and maintenance
✅ Server migration and environment setup
✅ CPU / memory / disk usage investigation

What I Offer:
✅ Linux environment inspection
✅ Website migration and deployment
✅ Nginx / PHP-FPM / MySQL / Redis troubleshooting
✅ Docker configuration and maintenance
✅ Server performance analysis
✅ Long-term remote operations support

Please contact me and mention: Linux Operations Consultation.

Contact Me:
Telegram: @shuijingwan
WeChat: 13980074657
Email: shuijingwanwq@gmail.com

评论

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.