Going green - Summer 24 update

9th August 2024

As part of our ongoing commitment to reduce the carbon footprint of BrandStencil, we are refactoring the application to be as energy efficient as possible.

BrandStencil is a large, complex codebase which has been written over many years, so there is a lot to do. We decided to start by looking at frequently run processes which are more `energy hungry` than others.

As a Brand Management and Artwork Automation tool, BrandStencil makes a lot of images. We have recently deployed a round of updates which focused on the generation of Thumbnail and Output Preview images for our template engine.

We used sustainable software principles and energy efficiency as the north star for all our technical decisions.

Caveat

The elephant in the room is of course measurement - knowing exactly how much energy your software is actually using.

At a recent talk in Brighton, Asim Hussain, Executive Director of the Green Software Foundation, said "You can't improve what you can’t measure".

The GSF have created the Impact Framework - a way to compute and report the environmental impacts of software applications accurately - but this is not a simple thing to set up and we haven’t started using it yet.

In the absence of data on energy usage we decided to work with three simple principles:

  1. Only make what you need (reduce processing)
  2. Only move what you need (reduce data in transit)
  3. Only keep what you need (reduce data at rest)

The following is an overview of what we did, it’s technically focussed for those of you interested in the details.

1. Only make what you need (reduce processing)

In BrandStencil Output Previews need to be high resolution so the user can zoom in and check all the fine details of their design. Additionally, we don’t want to compress them too much, jpeg artifacting would not be welcome. However, Thumbnails can get away with being much smaller and of a lower quality.

When generating a thumbnail, the old code rendered the designs at full size and then made a scaled-down copy of the image. When we wrote this code we only had a single renderer and it didn’t support scaling, so this was the only way to create an image which was smaller than the artwork. Our rendering capabilities had evolved enormously since then but this thumbnail code was still in use.

Our new code uses the compression and scaling capabilities of our new renderers to produce images which are as small as possible, in terms of file size and pixel size, without compromising the user experience. This means less energy is used to create them and we have eliminated the need to to resize.

When previewing multi-page templates we generate an image per page. However, if the template has `optional` pages, these may not always be populated. The old code generated an image for every page in the template and filtered out the blank ones afterwards.

As part of the refactor we created a method to check whether a page was populated before generating an image, so blank pages are never processed. This runs a simple regex on the design content, so uses a fraction of the processing power.

2. Only move what you need (reduce data in transit)

Our template engine now supports a number of different renderers - some run locally and others run as microservices in different locations, accessed via API requests.

The old code adhered to the factory pattern, so regardless of which renderer was called, the resulting image was always saved to the same location. This meant that calls to microservices needed to return the data of the generated image to be saved locally. This was great from a standardisation perspective but it wasn't very energy efficient to copy an image from one server to another if it was going to be deleted shortly afterwards.

With the refactor we changed the way the microservices worked so they could be used to serve images, as well as generate them. We updated the API so you could specify whether you wanted the request to return the image data or just the image URL.

This change greatly reduced the amount of data being passed from one place to another.

3. Only keep what you need (reduce data at rest)

Output Previews are only relevant for a moment, as soon as the design has been updated they become redundant. Thumbnails are made when a design is saved and kept until the next editing session.

We already had code in place to remove all Output Previews each night, but removing Thumbnails once they became redundant was more complicated.

We added an Observer to our design model which automatically deletes the current Thumbnail when a design is saved and a new one created. This also runs if a design is deleted so we don’t leave orphaned images in storage.

Lastly, we added a new property to our design model so we can monitor how many times an Output Preview is requested outside an editing session. This can be done from the user’s dashboard, by another user as part of the approval process or by an admin from the reporting area.

This data will help us decide whether it is more efficient to keep the last Output Preview from an editing session or continue to delete these nightly and re-generate on demand.

In conclusion

These are small steps, but they are heading in the right direction. With this round of updates we have reduced unnecessary requests and processes, reduced the amount of data we move around and reduced the amount of data we store.

A lot of this seems obvious, and looking back over the old code it was hard to justify some of the decisions we made; but when you're bootstrapping a web app and focused on shipping a working product, you don’t always have time to reflect on all the implications of your code.

If we are growing as developers we should always be able to look back at our own code and see how it could be enhanced. If we are also changing the way we think about code and shifting our focus to a more sustainable way of working, the possibilities to improve our work are endless.

Next up on our green coding roadmap

Logically `doing less` should result in a reduction in energy usage, but in the absence of actual energy consumption data we are working with assumptions. We have no way to measure the impact of the changes we have made.

The next steps are to try and benchmark some key processes - for example, how much energy is used to render a finished design as a print-ready A1 PDF?

We can then use this information, plus the data we are gathering in the application, to build a clearer picture and calculate how BrandStencil performs and how we can make changes which will result in a `measurable` impact.

It’ll take some time (we’re a small team) but we’re doing what we can and learning as we go.

Let's talk

Contact us

We are on our journey in sustainable software development with the mindset that every improvement, no matter how small can make a difference. If you have any ideas to help us please get in touch.