Handling Business Images in Web Applications  

READ ALSO: Image Variants in Web Applications

Across the millennium, a technical article explaining step by step how to save an image to—and read it from—a database column as a plain array of bytes was pure gold. At the time, images were almost invariably treated as separate files deployed in some folder on the web server.

Right or wrong, the idea of saving an image in a database and exposing it through a dedicated URL served by the same web application represented a quantum leap. I vaguely remember having authored one such article in the early 2000s, and it was quoted and referenced for quite some time.

Today, it’s a different story.

The scenario has changed significantly, in particular because of two factors that weren’t part of the equation in 2000: the cloud and mobile devices. Add to that the sheer volume of traffic modern applications handle, and it becomes clear why the answer to the question “How should we deal with images in web applications?” is considerably more nuanced today.

Core Facts

Before going any further, though, let me clarify one point. By images, here, we mean business images not certainly decorative images used by some CSS or HTML layout. A business image is an image that goes hand in hand with domain entities such as the photo of product, the flag of a country or the preview of document. Business images are almost never treated as public files served through an open and anonymous URL.

Speaking of images in web applications and APIs, two key facts stand out. First, search and manipulation (upload/delete/replacement), as well as backup, should be handled transactionally as if the image were native part of the parent entity.  Second, the physical storage medium where the image resides likely changes with the context.

Let’s now delve deeper into the most realistic storage options and related transactional concerns.

Storing in a Database Table

In a (relational or not) database table, images are stored as byte arrays directly inside VARBINARY columns alongside other traditional text or number columns. In other words, the image is treated as a constituent part of the entity saved into the record and may be easily edited and deleted transactionally in a single atomic operation. The typical type of a SQL column targeted to store large binary objects like images is VARBINARY, with an appropriate MAX size.

Interestingly, the MAX value doesn’t usually mean unlimited. Over 64K, and when the size is set to MAX, SQL Server reserves to store the data out-of-row, with the row containing only a reference to the actual bytes. For smaller sizes, the database can still opt to store the binary inside the data row. SQL Server swaps at 64K while, say, MySQL swaps storage at 8K. As mentioned, the MAX keywords, however, has a limitation, though very far. For SQL Server, it is 2GB.

What was an extremely smart approach 25 years ago, may not be the ideal approach today. Whether the database route is a viable approach or not essentially depends on how many images, and how large, you store and the frequency of reads and writes. The risk, in fact, is making the relational database infrastructure responsible for serving potentially large binary blocks most of its time. Not a huge concern for a few hundreds of images of relatively small size (say, <1MB). However, beyond the threshold, dealing with images increases the database workload, contributes to exhaust the I/O capacity, and slows down the overall performance competing with regular CRUD operations.  Last but not least, keeping too many images in the database makes backup massive and time consuming.

The Cloud Blob Storage

In a blob storage platform, images are treated as raw objects (namely, blobs) in distributed infrastructure such as Azure Blob Storage or AWS S3. Blob storage is analogous to a gigantic, persistent dictionary whose key is given by the full path name. Interestingly, the name of a blob object looks like a disk file—with its own list of parent folders, name, and extension—yet it is ultimately a single unique string. More precisely, a blob service is a collection of containers which are, in turn, similar to name/value dictionaries.

The major advantage of blobs is that the dictionary model allows direct lookup by key, conceptually giving you nearly O(1) access even in a distributed architecture. You don’t search through folders, enumerate files, or walk a tree to find an image: you know its key, and you ask the storage service for that key.

Compared to an in-memory dictionary, a blob is durable and possibly distributed across multiple physical servers. Noticeably, the distributed topology is not visible to developers or users and is buried in the blob access API. This factor delivers high scalability, zero load on the application’s server CPU for storing and serving the image itself, and effortless CDN integration, at the cost of setting up and dealing with a separate infrastructure and, when downloading content, the potential for a cross-region network hop.

The Application’s File System

In this case, image files are written directly to the local disk storage (e.g., wwwroot/images). It’s a quick and easy solution that is acceptable for files of frequent use that can be considered application’s assets. Great examples are flags, logos, icons and everything that is relatively static and constant. Technically, such images are served by the web server middleware for static files and remains the fastest and leanest approach.

Needless to say, it gets problematic in case of dynamic images that user may upload as part of their application’s experience. Modifying the deployed image, in  fact, is only possible if the App Service is writable. However, even if you configure the filesystem as writable, any change will not be in sync with the code repository (say, you update a logo for a quick fix but don’t have it saved on GIT…) and may not survive restart of the application and, worse yet, it won’t work across multiple instance of the same application, as each has its own filesystem.

(Most) Common Practice

No one-size-fits-all solution exists when it comes to using images in web scenarios. A common practice consists in splitting the storage of the image context on two media, part on a regular database table and part on a blob storage.

This practice is a trade-off between actual performance and effectiveness of core operations. If the image describes a product, for instance, the bytes of the image will go in a blob storage–the part that may really be large to write and read—whereas all metadata (product ID, content type, size, and whatever else may be relevant) will go in the database.

It must be considered that blob platforms are great at retrieving large chunks of data fast, but are really bad at searching whether a given image exists. Conversely, a database is great at locating an image out of smart queries but may incur in performance issues if too many large images may be requested for streaming.

The bottom line is that for a relatively small number of images, using the database only may be viable. Large numbers than a few hundreds, though, tend to favor blobs for two reasons: cost of storage (blobs are way cheaper for large amounts) and risk of pressure on the database throughput that may end up slowing down all operations, including those unrelated to the images themselves.

This said, not all the images a web application is called to manage must be stored in the same way. Depending on the context, some may go split between database and blob, while others (static in nature) will stay in the filesystem. Be aware, though, that anything in the filesystem realistically requires a new deployment in case of change.

In addition, consider that any application founded on images might need to deal with many variants of a single image, thus multiplying the total amount by a few factors (different color scheme, different size on a per–device basis, different quality). And this is a factor that loudly calls for a blob storage no matter the rest.

Published by D. Esposito

Software person since 1992

2 thoughts on “Handling Business Images in Web Applications  ”

Leave a Reply