Migrating from wkhtml2image to Playwright snapshots on AWS Lambda

Transitioning from wkhtmltoimage to Playwright for generating 5000+ receipts per day.

Migrating from wkhtml2image to Playwright snapshots on AWS Lambda
Serverless + Playwright

Unipage is the cheapest and fastest webshop solution for every type of restaurant, with over 1.400 active webshops to date.

90% of our customers at Unipage use a thermal printer to fulfill their incoming orders in their bar or kitchen. These receipts contain all the information they need to fulfill an order:

  • User details or table info
  • Products and prices
  • Payment status
  • Takeout time or delivery time
Thermal printed receipt

Thermal receipt printers often support a protocol called ESC/POS, a variant on the popular ESC/P printer control language, developed by Epson. Even though this protocol is widely adopted, it comes with many challenges and limits:

  • Implementation differs between printer models (and firmware versions)
  • Limited command set
  • Only a handful of supported fonts/weights
  • Epson-specific protocol
  • Table-based layout is very difficult to achieve
  • New features in ESC/POS require a firmware upgrade on the hardware

Initially, we offered some basic customization on the receipts:

  • Font size: small or large
  • Font: type A, type B or type C

Understandably, our customers were not satisfied with the level of personalisation we could achieve, so we started improving this user experience.

Receipt designer

To offer our customers the flexibility they need, we created an intuitive Receipt Designer. This designer allowed our customers to easily design their receipt to their specific needs.

Unipage receipt designer

Converting these personalised designs back to ESC/POS commands simply was not possible. Instead, we opted to render them in HTML and create a snapshot with wkhtmltoimage.

Simplified flow for snapshotting a receipt

This image bitmap would then be translated into a single bitmap ESC/POS command, and fed to the printer (over USB or network).

Sending an image to the printer requires us to convert translate it to ESC/POS

Suddenly, the thermal printers gained a ton of new tricks and we were able to offer our customers the flexibility they needed.

This worked beautifully for many years, and we generated over 1 million tickets using this technique.

Migrating to a serverless solution

Lately we’ve been getting reports that ticket printing is kinda slow on fridays — not coincidentally the most busy day of the week on our platform.

The order peak happens between 17:00–19:00, and during this time we receive on average around 2.500 orders.

wkhtmltoimage generates a ticket for an order synchronously, when requested. The process of generating a snapshot usually takes around 0.8s, and during this time a HTTP connection is held open.

At peak times, we often ran into the situation that 40+ wkhtmltoimage instances were generating snapshots at the same time — eating up resources of our machine and causing the delay our customers noticed.

Going serverless was on our mind for about a year, so we decided it was finally time to spend time and migrate. Thanks to Serverless, it was a delight to set up a Lambda function with an API gateway. We decided to abandon wkhtmltoimage and instead opt for a modern and robust solution: Playwright.

Simplified diagram for generating receipts through Playwright

We wanted to make this transition as transparent as possible for the clients using it, so we kept the original HTTP endpoint and simply introduced a 302 redirect to our new AWS API Gateway.

If the receipt has not yet been created before, we spin up a headless browser, create a snapshot and push it to S3. If the client already requested the receipt once before, we can immediately point to it since it’s stored on S3.

This setup allows us to asynchronously generate receipts with a queue mechanism, so we can optimise the speed even further.

Using feature flags we could easily A/B test both mechanisms and finetune the results of our Playwright solution until it was perfect.

Impact on speed

The impact was immediately noticeable, since the overall load on our server dropped by 7% at our peak times. Our customers responded positively to our efforts and confirmed that ticket printing is very consistent compared to before.

6.000+ receipts created on a friday

Deploying Playwright on Lambda was a true delight thanks to playwright-aws-lambda in combination with Serverless. The impact on our customers was immediately visible and they responded positively.

wkhtmltoimage has served us well in the past, but it was time to move on.

👋 Thanks for reading! Interested in learning more about Unipage?

Subscribe to sabatino.dev

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.