Four weeks to Shanghai: an event app served across the Great Firewall
For a major international motorsport event in Shanghai, we had four weeks to deliver a web app where regular and VIP participants could check their agendas. Hosting in mainland China was out of reach in that time, so we served the app from AWS in Hong Kong, through CloudFront and across the Great Firewall. It went live on time, the client's team in China reported no noticeable added latency, and the AWS bill for the month stayed in the single digits.
| Hosting in mainland China | What we shipped | |
|---|---|---|
| Prerequisites | ICP filing and an AWS China account | The client's existing AWS setup |
| Fits four weeks | No | Yes |
| Origin | A mainland China Region | S3 in Hong Kong (ap-east-1) |
| Path to users | Stays inside China | Crosses the Great Firewall |
| Servers to operate | Depends on the stack | None: every page is a static file |
| Monthly AWS bill | — | Single digits |
Context
The app itself sounded straightforward: a set of agenda pages, some for every participant and some for VIPs. The problems were around it. The event was in Shanghai, it was four weeks away, and the Chinese New Year holiday began the following week.
Our client operates in China, but there was no time to complete an ICP filing, the registration required for internet services hosted in mainland China. The client also wanted to use AWS, and AWS's mainland China Regions need a separate AWS China account. There was no time to get one of those either.
Constraints
- Four weeks, one of them a national holiday. During Chinese New Year, the client's team in China wasn't available to test.
- No ICP filing. Anything hosted in mainland China, including CDN edge locations there, was off the table.
- No AWS China account. The client wanted AWS, so the global AWS Regions were what we had.
- Reliable access from mainland China. Every request would cross the Great Firewall, which can add latency and drop traffic unpredictably.
- Agendas that change during the event. The client wanted each day's agenda taken down once that day was over.
The options
| Option | Needs ICP filing | Needs AWS China account | Fits four weeks | Verdict |
|---|---|---|---|---|
| AWS China Regions (Beijing, Ningxia) | Yes | Yes | No | Rejected |
| Another provider in mainland China | Yes | No | No | Rejected: ICP, and the client wanted AWS |
| AWS outside mainland China, nearby | No | No | Yes | Chosen, with the Great Firewall in the path |
Staying with AWS outside mainland China solved the account and regulatory problems in one move. The cost was that the app would reach its users through the Great Firewall, so the rest of the design was about making that crossing as short, as light and as rare as possible.
Architecture
- Build: Next.js with static site generation. The whole app is built ahead of time, so every page is a file.
- Origin: an S3 bucket in the AWS Hong Kong Region (
ap-east-1), as close to mainland China as our setup allowed. - Edge: CloudFront in front of the bucket. CloudFront's global network has no edge locations in mainland China, so attendees are served from nearby edges outside it.
- Account: a dedicated AWS account, upgraded to AWS Business Support for the event.
Key decisions and trade-offs
Static site generation with Next.js
We recommended static site generation (SSG) with Next.js, building and deploying the app ahead of time. We love SSG: it reduces operational overhead, makes effective caching straightforward, improves SEO and usually improves performance too. Here it also meant there was no server to keep alive on the far side of the Great Firewall, and nothing to scale when the whole event checked the agenda at once.
- Trade-off: every change is a deploy. Content can't change per request, so any update means a rebuild or an upload. For agendas fixed ahead of time, that was an easy trade.
A deliberately small payload
We limited the number of assets and made each one as small as we could, images above all. Every byte and every request has to cross the Great Firewall, so a smaller page is a faster page there, and one that is less likely to stall on a dropped connection.
We also kept third-party services out of the page. Fonts, analytics and scripts served from outside China are often slow or blocked there, and a single blocked request can hold up the whole page.
A Hong Kong origin
CloudFront serves most requests from its cache, but every cache miss travels back to the origin. Putting the bucket in Hong Kong, as close to mainland China as we could get, kept those trips short.
- Trade-off: an opt-in Region. Hong Kong has to be enabled on the account before it can be used. It's a small step, but one to take early when the deadline is four weeks away.
One route per day
We designed each day's agenda as its own static route. That decision paid off during the event, as described below.
Business Support for the event
We upgraded the dedicated AWS account to AWS Business Support so we could get faster answers if something went wrong. A generous trial period meant the upgrade didn't add to the project's cost.
Testing through the Great Firewall
During the holiday, we used publicly available testing services to confirm the app was reachable from mainland China and to estimate the extra latency. When the client's team in China came back from Chinese New Year, they tested the app regularly until go-live. They consistently reported that the latency added by the Great Firewall was not noticeable.
Running the event
The event ran from Friday to Sunday. At the client's request, once it was well past midnight in Shanghai, we removed the agenda for the day that had just ended. Because each day was its own route, we only had to invalidate that route in CloudFront. Every other route stayed cached, so the update didn't cause a single cache miss elsewhere.
Results
| Measure | Result |
|---|---|
| Time to go-live | On time: four weeks, including the Chinese New Year holiday |
| ICP filing or AWS China account | Neither needed |
| Latency added by the firewall | Not noticeable, as reported by the client's team in China |
| Servers to operate | None |
| Daily agenda updates | One CloudFront invalidation each, no other cache misses |
| AWS bill for the event month | Single digits |
The cost surprised even us. For a project of this profile and an end client of this calibre, the infrastructure was practically free. It's a good reminder that the right technical decisions can cut infrastructure costs dramatically.
We handled the software development, the deployment and the cloud infrastructure. We also investigated how to work within the restrictions of the Great Firewall and advised our client and the end client on the options. The project was delivered successfully, and the feedback from the client, the end client and its users was extremely positive.
What we'd do differently
- Monitor from inside China during the event. Testing from inside China relied on the client's team. A synthetic check running from mainland China networks would have given us the same answer around the clock.
- Automate the daily takedown. A scheduled job that removes the finished day and invalidates its route would avoid relying on someone being awake past midnight in Shanghai.
- Start the ICP filing anyway. If the event comes back next year, filing now would make hosting inside mainland China an option rather than a wish.
