%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Paper B -- Target: Environment Systems and Decisions (Springer), Q2
%% Carbon-aware storage-architecture selection for image-based time-series in
%% green IoT (three-way: MongoDB vs PostgreSQL-BYTEA vs PostgreSQL+MinIO).
%%
%% This manuscript consolidates two conference drafts (Postgre-vs-MongoDB and
%% Postgre-vs-Postgre+MinIO) into ONE three-way study and is now backed by a unified,
%% object-oriented benchmark harness that measures per-resolution carbon
%% DIRECTLY (one CodeCarbon tracker per engine x dimension x resolution) over a
%% single 360p->6K sweep with a common retrieval workload across all engines.
%% Data: ../data/  Figures: ../figures/  Harness: ../code/
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\documentclass[pdflatex,sn-basic]{sn-jnl}% Basic Springer Nature reference style (name-year). Add ",Numbered" if ESD requires numbered citations.

\usepackage{graphicx}%
\usepackage{multirow}%
\usepackage{amsmath,amssymb,amsfonts}%
\usepackage{booktabs}%
\usepackage{xcolor}%
\usepackage{textcomp}%
\usepackage{manyfoot}% required by sn-jnl (table footnotes / \SetFootnoteHook)
\usepackage{listings}%

\graphicspath{{figures/}{../figures/}}

% A small MongoDB-shell (JavaScript) language, since the listings package
% ships SQL but not JavaScript; visual styling is set in \lstset below.
\lstdefinelanguage{MongoJS}{
  morekeywords={db, var, let, const, function, return, true, false, null, new,
    ISODate, BinData, createCollection, createIndex, insertMany, find, sort,
    limit, aggregate, timeseries, timeField, metaField, granularity},
  sensitive=true,
  morecomment=[l]{//},
  morecomment=[s]{/*}{*/},
  morestring=[b]"
}

\lstdefinelanguage{PgSQL}[]{SQL}{
  morekeywords={BIGSERIAL,TIMESTAMPTZ,BYTEA,BIGINT,INTEGER,TEXT},
  morecomment=[l]{--}
}

\lstset{
  basicstyle=\ttfamily\scriptsize,
  keywordstyle=\color{blue}\bfseries,
  commentstyle=\color{gray}\itshape,
  stringstyle=\color{red},
  showstringspaces=false,
  breaklines=true,
  frame=lines,
  numbers=left,
  numberstyle=\tiny\color{gray},
  numbersep=6pt,
  xleftmargin=1.4em,
  framexleftmargin=1.4em,
  backgroundcolor=\color{lightgray!10},
  tabsize=2,
  columns=fullflexible}

\raggedbottom

\begin{document}

\title[Carbon-aware storage selection for image-based time-series in green IoT]{Carbon Footprint and Carbon-Aware Selection of Document-Oriented, Relational, and Hybrid Object-Relational Storage for Image-Based Time-Series Workloads in Green IoT}

% Author, affiliation, and email details removed for double-anonymous review.
\author*[1]{\fnm{}\sur{[Hidden for Double-blind Review]}}\email{}

\affil*[1]{\orgname{[Hidden for Double-blind Review]}}

\abstract{Smart-building and facility-monitoring deployments increasingly retain high-resolution image streams alongside timestamped metadata in a continuously running data tier, so the choice of storage backend is now a sustainability decision as much as a performance one. This paper measures and compares the carbon footprint of three storage architectures for image-based time-series workloads: the document database MongoDB (image embedded in each record), the relational database PostgreSQL/TimescaleDB (image inline in a binary column), and a hybrid that keeps metadata in PostgreSQL while offloading images to MinIO object storage. Using isolated containers and CodeCarbon with the processor's hardware energy counters, we benchmark resolutions from 360p to 6K, measuring carbon directly for every architecture, resolution, and operation under a common workload. The results reveal a resolution-dependent \emph{emission crossover with no universal winner}: MongoDB is greenest up to 1440p (one-twentieth of the costliest alternative at 360p, as tiny compressed buckets ingest fast), whereas the PostgreSQL+MinIO hybrid is greenest at 4K and above, roughly halving inline-storage emissions by decoupling the multi-megabyte payload from the database write path. MongoDB and the hybrid are mirror images, with inline PostgreSQL the pivot across the whole range. MongoDB cannot store 6K frames at all: its time-series bucketing packs several multi-megabyte images into one document that breaches the hard 16-megabyte limit. We translate the measurements into a carbon-aware decision framework and report Software Carbon Intensity, multi-region grid sensitivity, embodied-carbon implications of storage amplification, and a fleet-scale projection, turning the measurements into carbon-aware decision support for storage selection in sustainable building-monitoring infrastructure.}

\keywords{carbon footprint, green computing, sustainable IoT, time-series databases, image-based storage, decision support, life-cycle assessment, software carbon intensity, PostgreSQL, MongoDB, MinIO}

\maketitle

%%=====================================================================%%
\section{Introduction}\label{sec:introduction}
%%=====================================================================%%

Smart-building and facility-monitoring systems increasingly combine conventional telemetry with image streams from embedded cameras, smart doorbells, inspection devices, and other Internet-of-Things (IoT) edge devices---the expanding network of internet-connected sensors that observe the physical world~\citep{bajera_iot_smart_buildings,alfuqaha_iot_survey}. These applications retain binary media (the raw image files) together with timestamps, device identifiers, and other descriptive metadata so that operators can inspect the latest frame, replay recent events, or query activity over time~\citep{ceec_tsdb_review,jensen_tsms_survey}. Because the \emph{data tier}---the software layer that stores and serves this information---runs continuously (24 hours a day, on-site or at the network edge), its electricity use contributes directly to the operational carbon footprint of the building or infrastructure~\citep{nerc_tsdb_survey}. Data centres and on-premises information-technology (IT) equipment already account for a globally significant and growing share of electricity demand~\citep{masanet_datacenter_energy,shehabi_us_datacenter}, so as green-building standards increasingly account for the carbon cost of IT, the choice of storage system is no longer a purely technical decision: it is an environmental and infrastructure-management one~\citep{ieee_ce_definition}.

Organisations typically reuse general-purpose databases for this role rather than adopting specialised systems~\citep{intuz_iot_databases}. A \emph{database} here is the software that stores, indexes, and retrieves data; three database architectures dominate practice, and they differ chiefly in how they handle the bulky image payload (the data carried in each record). First, \emph{MongoDB}~\citep{mongodb_official} is a \emph{document-oriented} database---it stores each record as a self-contained, flexible document---and offers native Time-Series Collections, a storage mode tuned for timestamped data. It keeps each image embedded \emph{inside} the document in a compact binary form called BSON (Binary JSON, the binary encoding of the JavaScript Object Notation text format)~\citep{mongodb_bson_spec}, written to disk by its WiredTiger storage engine~\citep{mongodb_wiredtiger_storage} after general-purpose Snappy compression~\citep{google_snappy}. Second, \emph{PostgreSQL}~\citep{postgresql_official} is a \emph{relational} database, organising data as tables of rows and columns; with the TimescaleDB extension~\citep{timescaledb_official} it partitions a table into time-based chunks, and its built-in TOAST facility (The Oversized-Attribute Storage Technique) automatically relocates large values such as images into separate ``out-of-line'' storage~\citep{postgresql_toast_docs}. Third, a widely used \emph{hybrid} pattern keeps only the small, queryable metadata in PostgreSQL and offloads the bulky image to a dedicated \emph{object store}---a system specialised for holding large files as standalone objects---such as MinIO~\citep{minio_official} or the Amazon Simple Storage Service (S3)~\citep{aws_s3_official}. Because these designs move, copy, and compress the image differently, they can consume very different amounts of energy as image resolution---and therefore payload size---grows.

Existing time-series benchmarks (standardised performance tests) target lightweight numeric events~\citep{tsbs,cratedb_ts_benchmark,diva_timescaledb_mongodb_eval} and rarely evaluate multi-megabyte image payloads; even more rarely do they report energy use or carbon-dioxide-equivalent (CO\textsubscript{2}eq) emissions---the standard unit that converts the warming effect of all greenhouse gases into an equivalent mass of carbon dioxide. This leaves a practical gap for image-heavy IoT deployments that must decide which storage architecture minimises both execution time and carbon, and under which operating conditions. The gap matters because a storage system's behaviour changes fundamentally with payload size, so a conclusion drawn at one resolution need not hold at another.

This paper addresses the following research question: \emph{What is the carbon footprint of document-oriented, relational, and hybrid object-relational storage for image-based time-series workloads across increasing camera resolutions, and how should an operator choose among them to minimise emissions in green IoT infrastructure?} To answer it, we benchmark the three architectures across eight image resolutions from 360p to 6K, stored as JPEG files (Joint Photographic Experts Group, the ubiquitous lossy photo-compression standard)~\citep{wallace_jpeg}. Each architecture runs in its own isolated software container managed by Docker~\citep{docker_official}---a tool that packages software with its dependencies for reproducible execution---and we measure electricity use and emissions with CodeCarbon~\citep{codecarbon}, an open-source tool that records energy and estimates the resulting carbon by reading the processor's built-in Running Average Power Limit (RAPL) energy counters~\citep{david_rapl}, which report the actual energy drawn by the central processing unit (CPU) and memory. We analyse insertion throughput (how fast images are stored), retrieval latency (the delay in reading them back), storage amplification (disk space used relative to the raw data), and \emph{directly measured} per-resolution carbon. Unlike earlier conference studies [hidden for double-blind review], every resolution is measured under its own energy tracker (removing the need to estimate), and a single common read workload is applied to all three systems. We frame storage selection as an \emph{environmental-systems decision}---one that weighs operational and embodied carbon against performance and operational complexity for a given deployment's resolution mix and electricity grid---and the contributions are:

\begin{itemize}
  \item A three-way, directly measured carbon-footprint comparison of MongoDB, PostgreSQL-BYTEA (PostgreSQL storing each image inline in a binary column of type \texttt{BYTEA}, PostgreSQL's ``byte array'' type), and PostgreSQL+MinIO under identical image-based time-series workloads from 360p to 6K, quantifying CO\textsubscript{2}eq emissions with hardware energy measurement.
  \item Evidence of a \emph{resolution-dependent emission crossover} in which MongoDB and the hybrid are mirror images---MongoDB greenest at standard resolutions, the hybrid greenest at high resolutions, inline PostgreSQL the pivot---together with the finding that MongoDB cannot store 6K frames at all because its time-series bucketing breaches the 16~megabyte (MB) limit on a single BSON document.
  \item An environmental analysis that lifts the result beyond a performance benchmark: Software Carbon Intensity (SCI)---a standardised measure of carbon emitted per unit of useful work, defined by the international standard ISO/IEC~21031:2024~\citep{gsf_sci}---together with a multi-region electricity-grid sensitivity analysis (re-evaluating emissions under different regions' grid carbon intensities)~\citep{owid_carbon_intensity}, the \emph{embodied} carbon (manufacturing emissions) implied by storage amplification~\citep{tannu_ssd_embodied,gupta_chasing_carbon}, and a fleet-scale annual projection.
  \item A \emph{carbon-aware decision framework} that maps resolution and workload emphasis to the lowest-emission architecture, intended as decision support for sustainable building-monitoring infrastructure.
\end{itemize}

%%=====================================================================%%
\section{Related Work}\label{sec:related_work}
%%=====================================================================%%

\textbf{Time-series storage.} Time-series databases are designed for data that mostly arrives in timestamped order and is rarely modified afterwards. They sustain this append-oriented ingestion through time-based partitioning, compression, and storage layouts that reduce \emph{write amplification}---the tendency of a database to write substantially more data to disk than the application supplied, here by repeatedly rewriting the tree-structured on-disk indexes (B-trees) that locate records~\citep{dewaal_timeseries_survey,jensen_tsms_survey}. TimescaleDB~\citep{timescaledb_official} extends PostgreSQL with time-based table partitioning while preserving its standard query language, and MongoDB~\citep{mongodb_official} introduced native Time-Series Collections that \emph{bucket} (group) many measurements into compacted documents~\citep{mongodb_timeseries_collections_guide,mongodb_ts_best_practices}.

\textbf{Benchmarks and the binary-payload gap.} Most comparative benchmarks target lightweight scalar data: TSBS~\citep{tsbs} uses small DevOps/telemetry records, CrateDB's benchmark~\citep{cratedb_ts_benchmark} focuses on numeric IoT metrics, and the evaluation by \citet{diva_timescaledb_mongodb_eval} studies numerical sensor workloads. None characterise multi-megabyte image payloads, where the internal design of the storage system becomes decisive, and none report energy or emissions (Table~\ref{tab:relwork}). PostgreSQL's TOAST~\citep{postgresql_toast_docs} relocates oversized values out-of-line but keeps them within the database's transactional and retrieval machinery; MongoDB stores binaries inline in BSON documents~\citep{mongodb_bson_spec}, and its alternative for large files---GridFS, which splits a file into smaller chunks~\citep{mongodb_gridfs}---is incompatible with native Time-Series Collections~\citep{mongodb_ts_limitations}. Object stores such as MinIO~\citep{minio_official} instead stream large, unchanging objects directly while the relational system manages only lightweight metadata. The architectural trade-off is therefore not simply ``one system versus two'' but \emph{one transactional path for everything} versus \emph{separating metadata management from binary transport}.

\textbf{Carbon footprint of computing.} \citet{lannelongue_green_algorithms} formalised the Green Algorithms approach to quantifying the carbon footprint of computation, and \citet{strubell_energy_nlp} highlighted the energy cost of large-scale computation; CodeCarbon~\citep{codecarbon} provides a practical implementation that estimates energy and emissions from machine-level measurements and regional grid intensity. Beyond the energy consumed while running (\emph{operational} carbon), a growing literature stresses \emph{embodied} carbon---the emissions from manufacturing the hardware itself---as a first-class concern for sustainable systems~\citep{gupta_chasing_carbon}, with flash storage a notable contributor~\citep{tannu_ssd_embodied}. Facility-level accounting further multiplies computing energy by the Power Usage Effectiveness (PUE), the ratio of a data centre's total energy draw to the energy that actually reaches its computing equipment, which captures cooling and power-delivery overhead~\citep{shehabi_us_datacenter,masanet_datacenter_energy}. The Software Carbon Intensity specification~\citep{gsf_sci} standardises reporting of emissions per unit of useful work. Within database systems, however, little work applies per-operation carbon accounting to binary time-series storage. This study addresses that gap for document-oriented, relational, and hybrid object-relational image storage, and connects it to embodied carbon, PUE, grid intensity, and SCI.

\begin{table}[t]
\caption{Representative time-series benchmarks versus this work. We are unaware of prior work that benchmarks multi-megabyte image payloads \emph{and} reports energy/CO\textsubscript{2}.}\label{tab:relwork}
\small
\setlength{\tabcolsep}{4pt}
\begin{tabular}{@{}p{0.23\textwidth}p{0.17\textwidth}p{0.10\textwidth}p{0.14\textwidth}p{0.12\textwidth}@{}}
\toprule
Study & Payload type & Max payload & Engines & Energy / CO\textsubscript{2}? \\
\midrule
TSBS~\citep{tsbs} & numeric/scalar & $\sim$KB & multiple TSDBs & No \\
CrateDB benchmark~\citep{cratedb_ts_benchmark} & numeric IoT metrics & $\sim$KB & CrateDB et al. & No \\
\citet{diva_timescaledb_mongodb_eval} & numeric sensor & $\sim$KB & Timescale, Mongo & No \\
\textbf{This work} & \textbf{JPEG images} & \textbf{7.1~MB (6K)} & \textbf{Postgre, Mongo, PostMin} & \textbf{Yes (RAPL)} \\
\botrule
\end{tabular}
\end{table}

%%=====================================================================%%
\section{Methodology}\label{sec:methodology}
%%=====================================================================%%

\subsection{Hardware and software environment}\label{subsec:env}
All experiments execute on a single computer (Table~\ref{tab:env}) running Ubuntu~24.04.4~LTS (Linux 6.8.0) with an 11th-generation Intel Core i9-11900H processor (8~cores / 16~threads, 2.50--4.90~GHz), 30.99~GB of random-access memory (RAM; the computer's fast working memory), and a 1.9~TB Samsung solid-state drive (SSD; flash-based storage) on the high-speed Non-Volatile Memory Express (NVMe) interface. The host is in Indonesia; CodeCarbon uses the corresponding national grid carbon-intensity factor ($\approx$0.676~kilograms of CO\textsubscript{2}eq per kilowatt-hour, kg~CO\textsubscript{2}eq/kWh), i.e.\ the emissions associated with each unit of electricity consumed. Processor and memory energy are measured directly via the Intel RAPL hardware counters. The three architectures share the same host but run one at a time, in isolation, so that energy is attributed to the architecture under test. A single host with one client issuing requests sequentially is a deliberate \emph{controlled baseline}: it removes scheduling, contention, and network-topology confounds so the measured differences are attributable to each architecture's payload handling---the variable under study---and keeps the comparison fully reproducible. Because the emission crossover is driven by payload size, a structural property of each storage design, multi-client and distributed deployments are expected to shift the absolute figures but not the architectural ordering (Section~\ref{sec:discussion}).

\begin{table}[t]
\caption{Hardware and software environment (reproducibility).}\label{tab:env}
\small
\begin{tabular}{@{}ll@{}}
\toprule
Component & Version / setting \\
\midrule
CPU & Intel Core i9-11900H, 8C/16T, 2.50--4.90~GHz \\
RAM / SSD & 30.99~GB / 1.9~TB Samsung NVMe \\
OS & Ubuntu 24.04.4 LTS (Linux 6.8.0) \\
Containers & Docker 29.4.0, Compose v5.1.1 \\
PostgreSQL & 15 + TimescaleDB (\texttt{latest-pg15}) \\
MongoDB & 7.0 (\texttt{--wiredTigerCacheSizeGB 30}) \\
MinIO & \texttt{minio/minio:latest} \\
Runtime & Python 3.14, \texttt{psycopg2} 2.9.11, \texttt{pymongo} 4.17, \\
        & \texttt{minio} 7.2.20, Pillow 12.2.0, CodeCarbon 3.2.7 \\
Energy & Intel RAPL (CPU+RAM), \texttt{tracking\_mode=machine} \\
Grid factor & 0.676~kg~CO\textsubscript{2}eq/kWh (Indonesia) \\
\botrule
\end{tabular}
\end{table}

\subsection{Workloads and payloads}\label{subsec:workloads}
The benchmark harness generates deterministic JPEG payloads from a single source image---a freely-licensed photograph of Durdle Door, Dorset, UK~\citep{pexels_durdle_door}, resized to 6144$\times$3456---using a collage transform (Pillow), at quality~90. Eight resolutions are evaluated: 360p ($640{\times}360$, 0.09~MB), 480p ($854{\times}480$, 0.16~MB), 720p ($1280{\times}720$, 0.36~MB), 1080p ($1920{\times}1080$, 0.80~MB), 1440p ($2560{\times}1440$, 1.40~MB), 4K~UHD ($3840{\times}2160$, 2.99~MB), 5K ($5120{\times}2880$, 5.09~MB), and 6K ($6144{\times}3456$, 7.13~MB). Quality-90 JPEG retains high visual \emph{entropy}---fine, unpredictable detail that resists further compression---which leaves little for the databases' built-in compression to remove and reflects realistic conditions for storing real photographs. For each resolution the harness performs a 100-row warm-up (untimed priming inserts that bring caches to a steady state), then 5 measured insertion runs of 2{,}000 records each, submitted in batches of~50, followed by 5 measured bulk-retrieval runs and 5 measured latest-frame reads (each preceded by warm-ups). Each database is wiped and rebuilt between resolutions, and only the services needed by the architecture under test are running, so that energy is attributed fairly.

\subsection{Schema and operations}\label{subsec:schema}
\textbf{MongoDB (Mongo).} Each frame is one document in a native Time-Series Collection, with the image stored inline as \texttt{BinData} (BSON's binary type) and the metadata in a nested object; WiredTiger applies Snappy compression when writing to disk. Storing the image inline is the only native option here: MongoDB's large-file facility, GridFS, is incompatible with Time-Series Collections~\citep{mongodb_ts_limitations}, so this configuration reflects MongoDB's \emph{supported} design for timestamped media rather than a deliberately weak setup---the inline path is the one a practitioner adopting native time-series storage would actually use.

\textbf{PostgreSQL-BYTEA (Postgre).} Each frame is one row in a TimescaleDB time-partitioned table, with the image held inline in a \texttt{BYTEA} column and relocated out-of-line automatically by TOAST when it is large~\citep{postgresql_toast_docs}.

\textbf{PostgreSQL+MinIO (PostMin).} PostgreSQL stores the metadata plus a short reference key to the image; the image itself is uploaded to MinIO with an HTTP (Hypertext Transfer Protocol, the request/response protocol of the web) PUT request. Reading back first fetches the key from PostgreSQL and then streams the image from MinIO with an HTTP GET request.

All three architectures maintain a combined index on the device identifier and timestamp that accelerates ``latest-frame'' lookups. We measure four operations per architecture and resolution: (i)~insertion throughput and storage amplification; (ii)~\emph{bulk retrieval} (in database terms, full materialisation), which reads back every one of the 2{,}000 images in a time range and transfers its full content---the access pattern behind reviewing or exporting recent footage; (iii)~\emph{latest-frame read} (a single point read), the time to fetch the most recent image---the access pattern behind a live dashboard; and (iv)~driver round-trip overhead, the fixed cost of one minimal client--server exchange. The full schema, the three queries, and a step-by-step technical walk-through for all three architectures are given in Appendix~\ref{app:schemas}.

The two designs encode the \emph{same} logical record but place the image very differently---inline in the database (PostgreSQL \texttt{BYTEA} or MongoDB \texttt{BinData}) versus externalised to an object store (the hybrid)---which is the root of their contrasting energy profiles.

\subsection{Carbon-footprint measurement}\label{subsec:carbon_method}
Every combination of architecture, operation, and resolution runs inside its own CodeCarbon~\citep{codecarbon} energy tracker, so per-resolution energy and emissions are measured \emph{directly}, rather than estimated by spreading one coarse measurement across resolutions as in earlier work [hidden for double-blind review]. CodeCarbon reads processor and memory power via Intel RAPL and converts the total energy to CO\textsubscript{2}eq using the Indonesian grid intensity. Each tracker wraps an operation's \emph{entire} set of repeated runs (five insertion runs of 2{,}000 records, five bulk-retrieval runs, and five latest-frame reads); we therefore divide each integrated measurement by its run count and report the energy and emissions of a \emph{single} run---one batch of 2{,}000 inserts, one 2{,}000-image bulk retrieval, or one latest-frame read---which is the unit used throughout for Software Carbon Intensity, per-frame, and fleet figures. Throughput and latency are reported as means over the five runs with their standard deviations as a measure of run-to-run variability (Tables~\ref{tab:write}--\ref{tab:read}); carbon, by contrast, is a single integrated per-operation measurement and so carries no independent run-to-run dispersion---the small timing variability bounds it. Because emissions are simply energy multiplied by the grid intensity, the \emph{ranking} of the architectures depends on energy alone and is therefore the same in every region (Section~\ref{subsec:grid}).

\subsection{Failover and the unstorable cell}\label{subsec:failover}
To keep the measurements reliable and the data complete, each measurement is held in memory and saved only after it completes successfully; a measurement that fails is retried, and after repeated failures it is recorded as \emph{skipped} (with the architecture, resolution, number of attempts, and error) and the sweep continues to the next case. Exactly one case triggered this path: \textbf{MongoDB at 6K} (Section~\ref{subsec:bson}). The benchmark therefore reports a clean three-way comparison from 360p to 5K and a two-way PostgreSQL-versus-hybrid comparison at 6K, with the omission stated explicitly rather than silently mishandled.

%%=====================================================================%%
\section{Results}\label{sec:results}
%%=====================================================================%%

We report insertion throughput and storage amplification (Section~\ref{subsec:insert}), bulk retrieval and latest-frame reads (Section~\ref{subsec:retrieval}), the central per-resolution carbon comparison with its SCI and embodied-carbon implications (Section~\ref{subsec:carbon}), multi-region grid sensitivity (Section~\ref{subsec:grid}), and MongoDB's 16~MB ceiling (Section~\ref{subsec:bson}). All values are directly measured on identical hardware and CodeCarbon configuration; run-to-run variability is small for the carbon-dominating insertion and bulk-retrieval operations (coefficient of variation $\approx$1.6\% at the median and $<$8\% in the worst case; Tables~\ref{tab:write}--\ref{tab:read}), so differences of a few percent---such as the MongoDB--PostgreSQL near-tie at 4K---sit within measurement noise, whereas the order-of-magnitude crossovers are unambiguous; the per-operation winners are summarised in the decision framework (Section~\ref{sec:framework}).

\subsection{Insertion throughput and storage amplification}\label{subsec:insert}
Insertion (Figure~\ref{fig:insert}, Table~\ref{tab:write}) exhibits a monotone reordering with payload size. At low resolution MongoDB ingests much faster than the alternatives---4{,}194~rows/s at 360p, over $6\times$ PostgreSQL and $56\times$ the hybrid---because each frame compresses to a near-empty bucket (storage amplification $0.001\times$) that WiredTiger writes entirely in cache. PostgreSQL is the middle ingester at low resolution (batched inserts avoid a per-object network call), while PostMin pays the fixed cost of one MinIO PUT per payload and is slowest. As payloads grow the order inverts: MongoDB falls below PostgreSQL between 1440p and 4K and becomes the slowest engine at 4K--5K as WiredTiger serialises multi-megabyte BSON documents through B-tree pages~\citep{wiredtiger_btree_architecture} and compression no longer helps; PostMin, whose throughput is nearly flat, overtakes PostgreSQL at 4K and remains highest through 6K. Storage amplification (Figure~\ref{fig:storage}) explains much of the downstream carbon: Postgre holds a stable $\sim$1.04$\times$ (TOAST out-of-line layout) and PostMin $\sim$1.00$\times$ (raw object size) at all resolutions, whereas MongoDB changes sharply---$0.10\times$ at 1080p (Snappy compresses small, metadata-dominated documents) rising to $1.59\times$ at 4K and $3.00\times$ at 5K as high-entropy JPEG resists block compression.

\begin{figure}[t]
\centering
\includegraphics[width=\linewidth]{storage_amplification.pdf}
\caption{Storage amplification (disk space used $\div$ raw image size; the dashed line marks $1.0\times$, i.e.\ no overhead). PostgreSQL and the hybrid stay flat near $1.0\times$; MongoDB crosses from better-than-raw compression at low resolution to $3.0\times$ at 5K, with embodied-carbon consequences (Section~\ref{subsec:carbon}). Unlike the other metrics, this figure is shown on a linear axis only: the logarithmic companion is omitted because storage amplification is a ratio read against $1.0\times$ and, for MongoDB, falls to zero at low resolution (0.000 at 480p, 0.001 at 360p)---values a logarithmic axis cannot represent, since the logarithm of zero is undefined.}\label{fig:storage}
\end{figure}

\begin{figure}[t]
\centering
\includegraphics[width=\linewidth]{insert_throughput.pdf}
\caption{Insert throughput (records per second; mean$\pm$standard deviation over 5 runs), shown on a linear vertical axis (left) and a logarithmic one (right); the logarithmic panel makes the low-resolution behaviour visible. MongoDB dominates at low resolution but collapses at high resolution; the hybrid (PostMin) is flattest and leads from 4K. MongoDB is omitted at 6K (Section~\ref{subsec:bson}).}\label{fig:insert}
\end{figure}

\begin{table}[t]
\caption{Insert throughput (rows/s, mean$\pm$std) and storage amplification (on-disk $\div$ raw). Higher throughput and lower amplification are better; \textbf{bold} marks the best engine per row.}\label{tab:write}
\small
\setlength{\tabcolsep}{4pt}
\begin{tabular}{@{}lrrrrrr@{}}
\toprule
 & \multicolumn{3}{c}{Insert throughput (rows/s)} & \multicolumn{3}{c}{Storage amp. ($\times$)} \\
\cmidrule(lr){2-4}\cmidrule(lr){5-7}
Res. & Postgre & Mongo & PostMin & Postgre & Mongo & PostMin \\
\midrule
360p  & 640.9          & \textbf{4194.1} & 74.4          & 1.045 & \textbf{0.001} & 1.003 \\
480p  & 452.6          & \textbf{2532.4} & 44.7          & 1.044 & \textbf{0.000} & 1.002 \\
720p  & 185.7          & \textbf{760.3}  & 40.4          & 1.039 & \textbf{0.101} & 1.001 \\
1080p & 81.5           & \textbf{311.3}  & 34.4          & 1.039 & \textbf{0.101} & 1.000 \\
1440p & 43.8           & \textbf{114.2}  & 32.8          & 1.039 & \textbf{0.269} & 1.000 \\
4K    & 19.8           & 16.0            & \textbf{27.3} & 1.038 & 1.587 & \textbf{1.000} \\
5K    & 11.6           & 7.0             & \textbf{15.3} & 1.038 & 3.004 & \textbf{1.000} \\
6K    & 8.1            & --              & \textbf{13.1} & 1.038 & --    & \textbf{1.000} \\
\botrule
\end{tabular}
\footnotetext{Std deviations are small (e.g.\ MongoDB 360p $\pm$314; Postgre/PostMin typically $<2\%$). MongoDB at 6K is unstorable (Section~\ref{subsec:bson}).}
\end{table}

\subsection{Bulk retrieval and latest-frame reads}\label{subsec:retrieval}
Under a common workload across all three architectures, the read path tells the same mirror-image story (Figures~\ref{fig:retrieval}--\ref{fig:pointread}, Table~\ref{tab:read}). For \emph{bulk retrieval} of all 2{,}000 images, MongoDB's contiguous inline layout is fastest at low resolution (216~ms at 360p), but PostgreSQL degrades steeply as it pulls ever-larger \texttt{BYTEA} values out of out-of-line storage and through its client connection---reaching 53.6~s at 5K and 76.1~s at 6K. The hybrid is the most scalable reader: streaming objects over HTTP keeps bulk retrieval at 5.8~s (5K) and 8.6~s (6K), $9\times$ faster than inline PostgreSQL. \emph{Latest-frame reads} reinforce this: the hybrid stays near-flat (1--5~ms across the whole range) while PostgreSQL climbs to 39.6~ms at 6K and MongoDB to 69.8~ms at 5K. The hybrid is slightly slower than inline PostgreSQL only at the smallest resolutions, where its fixed HTTP round-trip (driver overhead 0.58~ms versus PostgreSQL's 0.05~ms) outweighs the streaming benefit.

\begin{figure}[t]
\centering
\includegraphics[width=\linewidth]{retrieval_latency.pdf}
\caption{Bulk-retrieval latency---the time to read back all 2{,}000 images in a range (milliseconds; mean$\pm$standard deviation), on linear (left) and logarithmic (right) axes. Inline PostgreSQL degrades steeply; the hybrid scales best.}\label{fig:retrieval}
\end{figure}

\begin{figure}[t]
\centering
\includegraphics[width=\linewidth]{point_read_latency.pdf}
\caption{Latest-frame read latency---the time to fetch the single most recent image (milliseconds; mean$\pm$standard deviation), on linear (left) and logarithmic (right) axes. The hybrid stays near-flat; the inline architectures climb with image size.}\label{fig:pointread}
\end{figure}

\begin{table}[t]
\caption{Read latency (ms, mean$\pm$std): bulk retrieval of all 2{,}000 images, and the latest-frame read. Lower is better; \textbf{bold} marks the best architecture per row.}\label{tab:read}
\small
\setlength{\tabcolsep}{4pt}
\begin{tabular}{@{}lrrrrrr@{}}
\toprule
 & \multicolumn{3}{c}{Bulk retrieval (ms)} & \multicolumn{3}{c}{Latest-frame (ms)} \\
\cmidrule(lr){2-4}\cmidrule(lr){5-7}
Res. & Postgre & Mongo & PostMin & Postgre & Mongo & PostMin \\
\midrule
360p  & 788.5    & \textbf{215.9}  & 1497.2 & 1.27 & 3.37 & \textbf{1.09} \\
480p  & 1377.0   & \textbf{479.4}  & 1487.5 & \textbf{0.97} & 3.67 & 1.93 \\
720p  & 3057.7   & 1188.5 & \textbf{1706.9} & 1.78 & 4.30 & \textbf{1.22} \\
1080p & 8238.6   & 2895.8 & \textbf{2211.2} & 3.88 & 5.17 & \textbf{1.78} \\
1440p & 13433.1  & 5286.8 & \textbf{2879.9} & 6.52 & 7.74 & \textbf{1.80} \\
4K    & 29883.8  & 11669.3 & \textbf{4273.0} & 17.06 & 25.38 & \textbf{2.12} \\
5K    & 53638.4  & 31821.2 & \textbf{5833.4} & 29.55 & 69.83 & \textbf{3.31} \\
6K    & 76059.0  & --     & \textbf{8634.5} & 39.59 & --    & \textbf{5.15} \\
\botrule
\end{tabular}
\end{table}

\subsection{Carbon footprint per resolution}\label{subsec:carbon}
Table~\ref{tab:carbon} and Figure~\ref{fig:carbon} report directly measured per-resolution emissions and constitute the central result. They reveal a \emph{resolution-dependent emission crossover with no universal winner}, in which MongoDB and the hybrid are mirror images and inline PostgreSQL is the pivot:
\begin{itemize}
  \item \textbf{Standard resolutions (360p--1440p): MongoDB is greenest}, and especially so at the low end---8~mg at 360p versus 38~mg (Postgre) and 187~mg (PostMin), a $4.8$--$23\times$ advantage---because near-empty compressed buckets ingest with little overhead. PostMin is the \emph{worst} here, penalised by a per-payload HTTP PUT on small images.
  \item \textbf{High resolutions (4K--6K): the hybrid is greenest}, emitting 526~mg at 4K and 1{,}023~mg at 5K---roughly half of inline PostgreSQL---by decoupling the multi-megabyte payload from the database write path. MongoDB is statistically indistinguishable from inline PostgreSQL at 4K (1{,}148 versus 1{,}128~mg, a $1.8\%$ gap that falls within insertion's run-to-run variability) and becomes \emph{clearly} the worst only at 5K (2{,}713~mg, $\approx 37\%$ above inline PostgreSQL) through inline BSON write amplification, defeated compression, and cache pressure, before failing entirely at 6K.
  \item \textbf{Inline PostgreSQL is the pivot}: it is never the greenest but operates across the whole range and avoids both extremes.
\end{itemize}
Insertion dominates the footprint (Figure~\ref{fig:breakdown}); bulk retrieval is the second contributor and latest-frame reads are negligible ($<1$~mg). Cumulatively over the common 360p--5K range, the hybrid is the lowest-carbon architecture at 3.13~g~CO\textsubscript{2}eq, $24.7\%$ below inline PostgreSQL (4.15~g) and $25.9\%$ below MongoDB (4.22~g): despite winning every standard resolution, MongoDB ends highest cumulatively because the high-resolution profiles dominate total energy. A CPU/RAM decomposition shows CPU accounts for $\approx$53\% of energy for the inline engines (Postgre, MongoDB) but only $\approx$41\% for the hybrid, consistent with PostMin offloading payload handling away from the database CPU path.

\begin{figure}[t]
\centering
\includegraphics[width=\linewidth]{carbon_per_resolution.pdf}
\caption{Directly measured carbon per resolution (milligrams CO\textsubscript{2}eq; insertion + bulk retrieval + latest-frame read), on a linear axis (left) and a logarithmic one (right). The linear panel conveys the magnitude of the high-resolution emissions, while the logarithmic panel reveals the full ``scissors'' crossover: MongoDB is greenest at $\le$1440p, the hybrid greenest at $\ge$4K, and inline PostgreSQL the pivot. MongoDB is omitted at 6K (Section~\ref{subsec:bson}).}\label{fig:carbon}
\end{figure}

\begin{figure}[t]
\centering
\includegraphics[width=0.85\linewidth]{carbon_breakdown.pdf}
\caption{Cumulative carbon over 360p--5K, split into insertion and read (bulk retrieval + latest-frame read) contributions. The hybrid is lowest overall; its read contribution is small because objects stream over HTTP rather than being pulled through the database.}\label{fig:breakdown}
\end{figure}

\begin{table}[t]
\caption{Directly measured carbon per resolution for one measured run: 2{,}000 inserts $+$ one 2{,}000-image bulk retrieval $+$ one latest-frame read (mg~CO\textsubscript{2}eq). Each tracker wrapped all five repeated runs, so every value is the integrated measurement divided by its run count. Lower is better; \textbf{bold} = greenest at that resolution.}\label{tab:carbon}
\small
\begin{tabular}{@{}lrrrl@{}}
\toprule
Res. & Postgre (BYTEA) & Mongo & PostMin (Postgre+MinIO) & Greenest \\
\midrule
360p  & 38.2    & \textbf{8.0}    & 186.6   & Mongo \\
480p  & 58.7    & \textbf{14.8}   & 298.2   & Mongo \\
720p  & 133.6   & \textbf{38.9}   & 317.6   & Mongo \\
1080p & 301.5   & \textbf{91.5}   & 370.5   & Mongo \\
1440p & 518.5   & \textbf{209.7}  & 407.0   & Mongo \\
4K    & 1128.0  & 1147.9 & \textbf{525.6} & PostMin \\
5K    & 1973.3  & 2712.9 & \textbf{1022.7} & PostMin \\
6K    & 2781.7  & --     & \textbf{1214.4} & PostMin \\
\midrule
\multicolumn{1}{@{}l}{Cum.\ 360p--5K} & 4151.8 & 4223.7 & \textbf{3128.2} & PostMin \\
\botrule
\end{tabular}
\footnotetext{Cumulative row over the common three-way range; MongoDB is highest cumulatively despite winning every standard resolution, because high-resolution profiles dominate total energy.}
\end{table}

\textbf{Software Carbon Intensity.} Expressing the storage operation in SCI terms~\citep{gsf_sci} with a functional unit of 1{,}000 stored frames (Table~\ref{tab:sci}), the carbon intensity of ingestion spans nearly three orders of magnitude across resolutions and inverts between engines: at 360p MongoDB stores 1{,}000 frames for 2.7~mg~CO\textsubscript{2}eq versus 83.6~mg for the hybrid, whereas at 5K the hybrid needs 467~mg versus MongoDB's 1{,}167~mg. SCI makes the operating-point dependence explicit and portable across deployments.

\begin{table}[t]
\caption{Software Carbon Intensity of ingestion: mg~CO\textsubscript{2}eq per 1{,}000 stored frames (Indonesian grid). Lower is better.}\label{tab:sci}
\small
\begin{tabular}{@{}lrrr@{}}
\toprule
Res. & Postgre & Mongo & PostMin \\
\midrule
360p  & 13.6   & \textbf{2.7}   & 83.6 \\
480p  & 20.0   & \textbf{4.4}   & 139.1 \\
720p  & 47.0   & \textbf{12.3}  & 147.4 \\
1080p & 103.4  & \textbf{28.8}  & 170.6 \\
1440p & 184.0  & \textbf{75.4}  & 184.0 \\
4K    & 399.3  & 506.2  & \textbf{232.0} \\
5K    & 686.1  & 1166.8 & \textbf{466.6} \\
6K    & 963.4  & --     & \textbf{542.6} \\
\botrule
\end{tabular}
\end{table}

\textbf{Carbon of the read operations.} The same crossover recurs within each read operation (Table~\ref{tab:dimcarbon}). For bulk retrieval, MongoDB is greenest up to 720p and the hybrid from 1080p---an earlier crossover than insertion, because the hybrid's HTTP streaming avoids pulling large values through the database engine. Latest-frame reads cost under 1~mg throughout and are led by the hybrid wherever the workload is non-trivial. Because insertion (Table~\ref{tab:sci}) is the dominant contributor, these per-operation winners carry through to the totals in Table~\ref{tab:carbon}.

\begin{table}[t]
\caption{Carbon of the two read operations (mg~CO\textsubscript{2}eq per single run: one 2{,}000-image bulk retrieval or one latest-frame read), completing the per-operation breakdown alongside insertion (Table~\ref{tab:sci}) and the total (Table~\ref{tab:carbon}). Lower is better; \textbf{bold} = greenest per row.}\label{tab:dimcarbon}
\small
\setlength{\tabcolsep}{4pt}
\begin{tabular}{@{}lrrrrrr@{}}
\toprule
 & \multicolumn{3}{c}{Bulk retrieval (mg)} & \multicolumn{3}{c}{Latest-frame (mg)} \\
\cmidrule(lr){2-4}\cmidrule(lr){5-7}
Res. & Postgre & Mongo & PostMin & Postgre & Mongo & PostMin \\
\midrule
360p  & 11.0   & \textbf{2.6}   & 19.4  & 0.04 & \textbf{0.03} & 0.05 \\
480p  & 18.8   & \textbf{6.0}   & 19.8  & 0.05 & \textbf{0.03} & 0.06 \\
720p  & 39.5   & \textbf{14.2}  & 22.8  & 0.06 & \textbf{0.05} & 0.06 \\
1080p & 94.5   & 33.8 & \textbf{29.2} & 0.09 & 0.08 & \textbf{0.06} \\
1440p & 150.4  & 58.9 & \textbf{38.9} & 0.13 & 0.11 & \textbf{0.06} \\
4K    & 329.2  & 135.2 & \textbf{61.6} & 0.25 & 0.32 & \textbf{0.07} \\
5K    & 600.7  & 378.5 & \textbf{89.4} & 0.39 & 0.88 & \textbf{0.09} \\
6K    & 854.4  & --    & \textbf{129.1} & 0.51 & --  & \textbf{0.11} \\
\botrule
\end{tabular}
\footnotetext{Latest-frame carbon is negligible in absolute terms ($<1$~mg); the hybrid leads it from 1080p upward, with MongoDB marginally lower only where all three are near zero.}
\end{table}

\textbf{Embodied carbon of storage amplification.} Operational energy is not the only cost: provisioned storage carries embodied (manufacturing) carbon~\citep{gupta_chasing_carbon,tannu_ssd_embodied}. At 5K, 2{,}000 frames occupy $\approx$9.9~GB of raw payload; PostMin provisions essentially that (9.9~GB) and Postgre $\approx$10.3~GB, but MongoDB's $3.00\times$ amplification provisions $\approx$29.8~GB. Using a representative NAND-flash embodied intensity of 0.16~kg~CO\textsubscript{2}eq/GB~\citep{tannu_ssd_embodied}, MongoDB carries $\approx$4.8~kg of embodied carbon for this data versus $\approx$1.6~kg for the hybrid---a one-time $\approx$3.2~kg penalty that recurs with every retained dataset and compounds at fleet scale through faster device wear. This is deliberately a first-order, single-factor estimate: it applies one representative cell-level NAND intensity to the \emph{storage medium only}---excluding controller, DRAM, packaging, transport, and end-of-life stages---and assumes embodied carbon scales linearly with provisioned capacity, so it conveys the order of magnitude and the \emph{direction} of the amplification penalty rather than a full life-cycle assessment; a complete LCA with device-specific boundaries is left to future work.

\subsection{Multi-region grid-intensity sensitivity}\label{subsec:grid}
\emph{Grid carbon intensity} is the mass of CO\textsubscript{2}eq released per unit of electricity generated, and it varies widely by region---from a few tens of grams per kilowatt-hour on hydro- or nuclear-dominated grids to over 700 on coal-heavy ones~\citep{owid_carbon_intensity}. The same computation therefore emits very different amounts of carbon depending on where it runs. A \emph{multi-region grid-intensity sensitivity} analysis re-evaluates the carbon footprint under several such regional grids to test how robust the conclusions are to the deployment location. Because emissions equal energy times grid intensity, the architecture \emph{ranking} is grid-invariant while the \emph{absolute} footprint scales with the local grid (Table~\ref{tab:grid}). Recomputing the cumulative 360p--5K footprint across representative national grids~\citep{owid_carbon_intensity} from near-decarbonised (Sweden, 41~g/kWh) to coal-heavy (India, 713~g/kWh), the hybrid remains the lowest-carbon choice everywhere, and the absolute saving versus MongoDB grows from 0.066~g (Sweden) to 1.16~g (India) for this modest 2{,}000-frame-per-resolution workload. Grid decarbonisation shrinks the absolute stakes but does not change which architecture an operator should choose. We therefore present this sweep as a bounding exercise---a linear rescaling of one measured energy figure---rather than an independent finding. The carbon-specific results that do \emph{not} reduce to operational energy are the embodied-carbon penalty of storage amplification (Section~\ref{subsec:carbon}), which scales with provisioned capacity rather than runtime, and the operating-point inversion made explicit by Software Carbon Intensity; these are where the carbon lens adds information beyond a conventional energy benchmark.

\begin{table}[t]
\caption{Multi-region grid sensitivity: cumulative footprint over 360p--5K (g~CO\textsubscript{2}eq) under different grid intensities. The hybrid (PostMin) is greenest under every grid.}\label{tab:grid}
\small
\begin{tabular}{@{}lrrrr@{}}
\toprule
Grid region & g/kWh & Postgre & Mongo & PostMin \\
\midrule
Sweden            & 41  & 0.25  & 0.26  & \textbf{0.19} \\
France            & 53  & 0.33  & 0.33  & \textbf{0.25} \\
EU-27 average     & 230 & 1.41  & 1.44  & \textbf{1.06} \\
United States     & 360 & 2.21  & 2.25  & \textbf{1.67} \\
China             & 550 & 3.38  & 3.44  & \textbf{2.55} \\
Indonesia$^\ast$  & 676 & 4.15  & 4.22  & \textbf{3.13} \\
India             & 713 & 4.38  & 4.45  & \textbf{3.30} \\
\botrule
\end{tabular}
\footnotetext{$^\ast$Baseline grid used for all other tables. Grid intensities are representative national values~\citep{owid_carbon_intensity}; exact figures vary by year and data source.}
\end{table}

\subsection{The MongoDB 16~MB ceiling}\label{subsec:bson}
MongoDB could not store 6K frames at all. The 6K payload is 7.13~MB---comfortably within the 16~MB BSON document limit for a single frame---yet insertion failed with error~10334 (\texttt{BSONObjectTooLarge}), the offending object measuring 22.4~MB ($\approx$3$\times$ the payload). The cause is architectural: native Time-Series Collections \emph{bucket} multiple measurements that share a metadata value into a single underlying bucket document, which is itself bound by the 16~MB BSON limit. With multi-megabyte payloads only two frames fit in a bucket; the attempt to bucket a third breaches the ceiling. The same bucketing that makes time-series collections efficient for small measurements becomes a hard limit for large binaries, and---unlike a tuning parameter---it cannot be raised. This is a decision-relevant constraint: \emph{MongoDB inline storage is not merely inefficient but infeasible} once payloads approach a few megabytes, independent of cache size or hardware.

%%=====================================================================%%
\section{A Carbon-Aware Decision Framework}\label{sec:framework}
%%=====================================================================%%

\subsection{Which architecture wins each operation}\label{subsec:winners}
Bringing the operations together (Table~\ref{tab:winners}), two regularities define the result and motivate a single decision rule. First, in every operation the lowest-carbon architecture is also the best-performing one, at every resolution. This is not a coincidence: emissions are proportional to energy, and energy is power integrated over time, so the architecture that completes an operation fastest almost always emits the least doing it. The carbon question and the performance question therefore share the same answer for each operation, which is convenient for practitioners who can optimise for speed and carbon at once. Second, each operation exhibits the same MongoDB--hybrid ``scissors'' with an operation-specific crossover: storage and insertion favour MongoDB up to 1440p and the hybrid from 4K; bulk retrieval crosses earlier (MongoDB up to 720p, the hybrid from 1080p); and latest-frame reads favour the hybrid almost throughout. Inline PostgreSQL is the single best at no operation, yet it is the worst at none either, and---unlike MongoDB---it operates across the whole 360p--6K range.

\begin{table}[t]
\caption{Which architecture wins each operation, and at which resolutions, for performance and for carbon. The greenest architecture coincides with the best-performing one throughout. Postgre = PostgreSQL-BYTEA; Mongo = MongoDB; PostMin = PostgreSQL+MinIO (hybrid).}\label{tab:winners}
\small
\begin{tabular}{@{}p{0.22\textwidth}p{0.31\textwidth}p{0.31\textwidth}@{}}
\toprule
Operation & Best performance & Greenest (lowest carbon) \\
\midrule
Storage footprint & Mongo ($\leq$1440p), PostMin ($\geq$4K) & Mongo ($\leq$1440p), PostMin ($\geq$4K) \\
Insertion (storing) & Mongo ($\leq$1440p), PostMin ($\geq$4K) & Mongo ($\leq$1440p), PostMin ($\geq$4K) \\
Bulk retrieval & Mongo ($\leq$720p), PostMin ($\geq$1080p) & Mongo ($\leq$720p), PostMin ($\geq$1080p) \\
Latest-frame read & PostMin (all; Postgre at 480p) & PostMin (all; Mongo marginal $\leq$720p) \\
\botrule
\end{tabular}
\footnotetext{MongoDB is omitted at 6K (Section~\ref{subsec:bson}); the hybrid wins both performance and carbon at 6K for every operation.}
\end{table}

\subsection{Selecting an architecture by operating regime}\label{subsec:selection}
The measurements translate into operational guidance for sustainable building-monitoring infrastructure. The dominant decision variable is camera resolution (a proxy for payload size); the secondary variable is workload emphasis (write-heavy ingestion, read-heavy analytics, or storage-bound archival). Table~\ref{tab:decision} summarises the carbon-aware recommendation. The rule is simple and crossover-driven: below $\sim$1440p choose MongoDB; from 4K upward choose the hybrid; choose inline PostgreSQL when resolution is mixed/uncertain or operational simplicity is paramount; and never choose MongoDB once payloads approach the BSON ceiling.

\begin{table}[t]
\caption{Carbon-aware architecture selection. Postgre = PostgreSQL-BYTEA; Mongo = MongoDB; PostMin = PostgreSQL+MinIO.}\label{tab:decision}
\small
\begin{tabular}{@{}p{0.27\textwidth}p{0.13\textwidth}p{0.46\textwidth}@{}}
\toprule
Operating regime & Choice & Rationale \\
\midrule
$\leq$1440p, ingest-heavy & Mongo & Greenest by $4.8$--$23\times$; near-zero storage amplification; fastest completion dominates carbon. \\
$\geq$4K, any emphasis & PostMin & $\sim$half the carbon of inline storage; flat storage; HTTP streaming makes reads cheap. \\
Mixed / uncertain resolution & Postgre & Consistent pivot: never worst, single transactional boundary, operates over the full range. \\
Storage-bound / archival & PostMin & $\sim$1.00$\times$ amplification minimises operational \emph{and} embodied carbon. \\
High-resolution read-heavy & PostMin & Object streaming keeps latest-frame and bulk-retrieval latency and energy low. \\
$\geq$6K ($\approx$7~MB/frame)$^\dagger$ & Postgre or PostMin & MongoDB \emph{infeasible}: bucketed documents exceed the 16~MB BSON limit. \\
\botrule
\end{tabular}
\footnotetext{$^\dagger$A single 6K frame ($\approx$7~MB) is itself well within MongoDB's 16~MB per-document limit; the limit is breached not by one payload but because MongoDB's native time-series \emph{bucketing} groups several multi-megabyte frames into one internal bucket document, whose combined size exceeds 16~MB (see Section~\ref{subsec:bson}).}
\end{table}

\subsection{From per-frame carbon to fleet scale}\label{subsec:fleet}
To make the emissions actionable without assuming a particular installation, we express them as a measured \emph{per-frame} rate that a reader can scale to any deployment. At 4K, storing one frame costs a directly measured $0.232$~mg~CO\textsubscript{2}eq with the hybrid, $0.399$~mg with inline PostgreSQL, and $0.506$~mg with MongoDB. These per-frame rates are obtained directly from the measurements: each is the 4K per-run insertion emission (one run of $2{,}000$ inserts) divided by those $2{,}000$ frames---equivalently, the Software Carbon Intensity reported in Table~\ref{tab:sci} (mg~CO\textsubscript{2}eq per $1{,}000$ frames) divided by $1{,}000$. The hybrid's advantage over inline PostgreSQL is therefore $0.167$~mg per stored frame. Treating the measured per-frame rate as constant, an operator obtains a first-order annual footprint by multiplying it by their camera count, capture rate, and retention period (and by a data-centre Power Usage Effectiveness factor, $\approx$1.5~\citep{shehabi_us_datacenter}, for the facility total); at very large scale the rate may drift with batching, contention, and database growth, so this is an estimate rather than a guarantee. As a single normaliser to fix scale, take $1{,}000$ cameras each capturing one frame per minute for a year: that is $1{,}000\times60\times24\times365=5.26\times10^{8}$ stored frames. The annual carbon is then the per-frame rate times this frame count, converting milligrams to kilograms---for the hybrid, $0.232~\mathrm{mg}\times(5.26\times10^{8})/10^{6}\approx122$~kg~CO\textsubscript{2}eq. The three architectures' annual footprints are summarised in Table~\ref{tab:fleet}. Concretely, in a case where an organisation decides to migrate its 4K image tier from inline PostgreSQL (Postgre) to the hybrid (PostMin), it would reduce its ingestion carbon footprint by $\approx$88~kg~CO\textsubscript{2}eq per year for every $1{,}000$ cameras (at one frame per minute)---a reduction comparable to driving an average passenger car about $520$~km (at a representative $\approx$0.17~kg~CO\textsubscript{2}eq per vehicle-km~\citep{desnz_ghg_factors}), or to the yearly CO\textsubscript{2} uptake of about four mature trees (taking $\approx$21~kg~CO\textsubscript{2} per tree per year~\citep{nowak_urban_trees}). This normaliser is illustrative, not a claim about a specific site; the underlying quantity is the measured per-frame rate.

\begin{table}[t]
\caption{Per-frame 4K carbon (directly measured) scaled to a fleet. The annual columns multiply the per-frame rate by an \emph{illustrative} normaliser of $1{,}000$ cameras $\times$ 1 frame/min $\times$ 1 year ($5.26\times10^{8}$ frames); for any other deployment, multiply the per-frame rate by the actual camera count, capture rate, and retention. Postgre = PostgreSQL-BYTEA; Mongo = MongoDB; PostMin = PostgreSQL+MinIO (hybrid).}\label{tab:fleet}
\small
\begin{tabular}{@{}lrrr@{}}
\toprule
Architecture & Per frame & Per normaliser & With PUE 1.5 \\
             & (mg) & (kg/yr) & (kg/yr) \\
\midrule
PostMin (hybrid) & \textbf{0.232} & \textbf{122}   & \textbf{183}   \\
Postgre (BYTEA)  & 0.399          & 210            & 315            \\
Mongo            & 0.506          & 266            & 399            \\
\midrule
Saving (Postgre $\rightarrow$ PostMin) & 0.167 & 88 & 132 \\
\botrule
\end{tabular}
\footnotetext{Per-frame rate $=$ per-run 4K insertion carbon (one run of 2{,}000 inserts) $\div$ 2{,}000. Annual $=$ per-frame rate (mg) $\times$ cameras $\times$ frames per camera per year $/\,10^{6}$ (at 1 frame/min, $60\times24\times365=525{,}600$ frames/yr); computed from unrounded rates. The $\approx$88~kg/yr saving $\approx$ $520$~km of car travel $\approx$ annual CO\textsubscript{2} uptake of about four mature trees. Multiply linearly for other fleets.}
\end{table}

\subsection{Alignment with Sustainable Development Goals}\label{subsec:sdg}
Carbon-aware storage selection contributes to several of the United Nations Sustainable Development Goals (SDGs), the 2030 agenda of seventeen global targets for sustainability~\citep{un_sdg}: SDG~7 (affordable and clean energy) and SDG~13 (climate action) through direct reductions in operational and embodied emissions; SDG~9 (industry, innovation, and infrastructure) and SDG~11 (sustainable cities and communities) by informing greener building-monitoring infrastructure; and SDG~12 (responsible consumption and production) by curbing the over-provisioning of storage through amplification-aware design.

%%=====================================================================%%
\section{Discussion}\label{sec:discussion}
%%=====================================================================%%

\textbf{Why the crossover occurs.} The three engines occupy different points on a single trade-off between fixed per-operation overhead and per-byte payload handling. MongoDB's inline BSON layout is highly efficient while documents stay small and cache-resident: buckets compress to near-nothing and ingest in cache. But WiredTiger keeps documents in their \emph{uncompressed} form in working memory and writes the entire BSON document---including the multi-megabyte image---through its on-disk index pages~\citep{wiredtiger_btree_architecture}; as payloads grow, Snappy~\citep{google_snappy} no longer compresses high-entropy JPEG, storage amplification climbs to $3.00\times$, and at the largest sizes the memory cache fills, forcing the system to evict data to disk and stalling the writes in progress~\citep{percona_wiredtiger_eviction}. PostgreSQL's TOAST~\citep{postgresql_toast_docs} relocates images out-of-line, keeping the main index compact and the write path roughly independent of resolution ($1.04\times$), which yields stable, middle-of-the-road carbon. The hybrid removes the image from the relational database entirely, so PostgreSQL records only metadata---its write-ahead log (WAL, the change journal a database writes before applying updates, used for crash recovery) and indexes grow with the metadata rather than the image size---while MinIO streams the object; this is the most energy-efficient path once payloads are large, at the cost of a fixed HTTP round-trip that makes it the worst choice for small images.

\textbf{Implications for green building monitoring.} There is no single ``green database.'' Standard-definition camera streams are greenest on MongoDB; high-resolution inspection or surveillance streams are greenest on PostgreSQL+MinIO; inline PostgreSQL is the safe default when resolution is mixed or operational simplicity (a single transactional boundary, simpler backup/recovery) is valued. The 16~MB bucket ceiling further removes MongoDB from consideration for $\geq$6K media regardless of carbon. These map directly to the infrastructure decisions in Table~\ref{tab:decision}.

\textbf{Operational trade-offs.} The hybrid introduces two services with independent failure modes and a two-step write (a database insert plus a MinIO upload) that is not \emph{atomic}---the two steps can succeed or fail independently, so a crash in between can leave an image without its metadata or vice versa---and therefore requires clean-up logic such as periodically deleting orphaned objects. Inline PostgreSQL keeps everything within a single all-or-nothing transaction. These operational costs must be weighed against the hybrid's carbon and storage advantages at high resolution. Because the underlying mechanism---inline large-object handling versus externalised object transport---is generic, the qualitative crossover is expected to transfer to other relational engines with large-object columns, though exact crossover points depend on each engine's page layout and logging. For the same reason we pair the object store with PostgreSQL only: once the payload is externalised, the metadata engine contributes a small, payload-independent overhead, so a MongoDB+MinIO hybrid would closely track PostgreSQL+MinIO. We therefore keep the comparison on the decisive inline-versus-externalised axis rather than adding a fourth, largely redundant arm.

\textbf{Threats to validity.} Results are from a single host and container topology; distributed deployments may differ, though the relative comparison holds because all engines ran under identical conditions. Per-resolution emissions are now directly measured (removing the estimation assumption of earlier work [hidden for double-blind review]), but energy accuracy depends on the Intel RAPL counters; on computers where RAPL is unavailable, CodeCarbon falls back to Thermal Design Power (TDP) estimates---nameplate power ratings rather than live measurement. Each cell's carbon is a single integrated CodeCarbon measurement normalised to one run rather than a five-run mean; the low run-to-run variability of the underlying insertion and retrieval timings bounds its uncertainty, and independent repeated energy runs would tighten the per-cell estimate---a straightforward extension. We benchmark a single client issuing requests sequentially; multi-client concurrency is effectively a \emph{different} study, because it changes how energy is attributed and introduces contention noise. Single-client sequential access is, by contrast, a clean and reproducible baseline, and since the emission crossover is driven by payload size---a structural property of each storage design---rather than by client count, we expect concurrency to shift the \emph{absolute} figures but not the architectural ordering; a multi-client evaluation is therefore a reasonable item to leave for future work. Likewise, the batch size is fixed at~50: larger batches mainly reduce per-round-trip overhead for the inline engines (Postgre and Mongo) but not the one-object-per-PUT cost of the hybrid, so the crossover is expected to be robust to batching, and a batch-size sweep is a natural extension. Payloads are deterministic collages built from a single real photograph~\citep{pexels_durdle_door} rather than a diverse image corpus, so they carry the entropy of real photographic content rather than computer-generated data. Because each stored record is an independent image, its storage, write amplification, and energy cost depend on the payload's size and entropy---not on any temporal relationship between frames---so a real still image is a representative payload and real \emph{video} is not required for this storage-oriented comparison (video would matter only for inter-frame or streaming codecs, which we do not study). The main remaining limitation is scene diversity---a single coastal scene---but the controlling variable for storage, amplification, and energy is the JPEG's \emph{entropy} (its compressibility), not its subject matter: the quality-90 photographic payload is already a high-entropy case that leaves little for database compression to remove, approximating the worst case for the inline engines. A broader real-image corpus would therefore refine the absolute amplification and carbon figures but is not expected to move the inline-versus-externalised ordering. Finally, the embodied-carbon and fleet figures are first-order estimates using representative published factors and stated assumptions, intended to convey magnitude rather than site-specific precision.

%%=====================================================================%%
\section{Conclusion}\label{sec:conclusion}
%%=====================================================================%%

This paper measured the carbon footprint of three storage architectures---document-oriented MongoDB, relational PostgreSQL-BYTEA, and hybrid PostgreSQL+MinIO---for image-based time-series workloads from 360p to 6K, using CodeCarbon with RAPL hardware energy measurement, with carbon measured directly for every architecture, resolution, and operation and a common retrieval workload across all three engines. The key finding is a resolution-dependent emission crossover with no universal winner: MongoDB is greenest up to 1440p (by as much as $23\times$ at 360p), the hybrid is greenest from 4K (roughly halving inline-storage carbon and lowest cumulatively, by $\approx$25\%), and inline PostgreSQL is the pivot---while MongoDB is infeasible at 6K because time-series bucketing breaches the 16~MB BSON limit. We translated the measurements into a carbon-aware decision framework and supported it with Software Carbon Intensity, multi-region grid sensitivity, embodied-carbon implications of storage amplification, and a fleet-scale projection.

Future work will extend the study to distributed and multi-client deployments, incorporate real (variable-entropy) image feeds, broaden the embodied-carbon and PUE accounting with site-specific factors, and validate the decision rule on held-out monitoring workloads. A public artifact---benchmark code, Docker configurations, and raw results---accompanies the paper to support reproduction.

\backmatter

% Acknowledgements (incl. funding and the generative-AI-use disclosure) are entered in the
% submission system's declaration fields for double-anonymous review -- see ../declarations/.
% Not included in the manuscript per ESD double-anonymous policy.

% Declarations (funding, competing interests, ethics/consent, data & code availability,
% author contributions) are entered in the submission system for double-anonymous review;
% ready-to-paste text is in ../declarations/. Per ESD policy they are not included here.

\begin{appendices}

\section{Schemas and queries}\label{app:schemas}
This appendix gives, for each architecture, the schema and the three data operations used by the benchmark harness, exactly as issued (columns abbreviated for space). In PostgreSQL (Listing~\ref{lst:pg}) the image is held inline in a \texttt{BYTEA} column of a TimescaleDB hypertable, where TOAST relocates it out-of-line automatically: insertion is a batched parameterised \texttt{INSERT} (50 rows per round-trip), bulk retrieval is a single time-range \texttt{SELECT} streamed through a server-side cursor, and the latest-frame read is an indexed \texttt{ORDER BY ts DESC LIMIT 1}. In MongoDB (Listing~\ref{lst:mongo}) each frame is one document in a native time-series collection with the image inline as \texttt{BinData}; the equivalent operations are an \texttt{insertMany}, a time-range \texttt{find} projected to the payload, and a \texttt{find}/\texttt{sort}/\texttt{limit} for the latest frame. The hybrid (PostMin, Listing~\ref{lst:pm}) shares the relational schema but replaces \texttt{payload\_data BYTEA} with a \texttt{minio\_object\_key TEXT} reference: on insertion the image is uploaded to MinIO with \texttt{put\_object} and only the key is written to PostgreSQL, and each read first fetches the key from PostgreSQL and then streams the object from MinIO with \texttt{get\_object}.

\begin{lstlisting}[language=PgSQL,caption={PostgreSQL-BYTEA (Postgre): TimescaleDB schema and the three data operations (image stored inline as \texttt{BYTEA}).},label={lst:pg}]
-- Schema: hypertable with the image inline as BYTEA (TOAST stores it out-of-line)
CREATE TABLE sensor_media (
  sample_id BIGSERIAL NOT NULL, device_id BIGINT NOT NULL, ts TIMESTAMPTZ NOT NULL,
  payload_data BYTEA NOT NULL, payload_size_bytes INTEGER NOT NULL,
  width INTEGER, height INTEGER, mime_type TEXT NOT NULL,
  PRIMARY KEY (ts, sample_id));
SELECT create_hypertable('sensor_media', by_range('ts'));
CREATE INDEX idx_device_ts_desc ON sensor_media (device_id, ts DESC);

-- Insert: batched, 50 rows per round-trip
INSERT INTO sensor_media (device_id, ts, payload_data, payload_size_bytes, ...)
VALUES (%s, %s, %s, %s, ...);

-- Bulk retrieval: every frame in a time range
SELECT ts, payload_data FROM sensor_media
WHERE device_id = %s AND ts >= %s AND ts <= %s ORDER BY ts;

-- Latest-frame read
SELECT ts, payload_data FROM sensor_media
WHERE device_id = %s ORDER BY ts DESC LIMIT 1;
\end{lstlisting}

\begin{lstlisting}[language=MongoJS,caption={MongoDB (Mongo): native time-series collection schema and the same operations (image stored inline as \texttt{BinData}).},label={lst:mongo}]
// Schema: native time-series collection, image inline as BinData
db.createCollection("sensor_media", {
  timeseries: { timeField: "ts", metaField: "meta", granularity: "seconds" } });
db.sensor_media.createIndex({ "meta.device_id": 1, "ts": -1 });

// Insert: batched, 50 documents per insertMany; each frame is one document
db.sensor_media.insertMany([
  { meta: { device_id: 1, profile: "4k", payload_kind: "image" },
    ts: ISODate("..."), payload_data: BinData(0, "<jpeg bytes>"),
    payload_size_bytes: 3138125, width: 3840, height: 2160, mime_type: "image/jpeg" },
  /* ... */ ]);

// Bulk retrieval: every frame in a time range
db.sensor_media.find(
  { "meta.device_id": 1, ts: { $gte: tMin, $lte: tMax } },
  { ts: 1, payload_data: 1, _id: 0 }).sort({ ts: 1 });

// Latest-frame read
db.sensor_media.find({ "meta.device_id": 1 }).sort({ ts: -1 }).limit(1);
\end{lstlisting}

\begin{lstlisting}[language=PgSQL,caption={PostgreSQL+MinIO (PostMin): the relational schema stores a MinIO object key in place of the image, so each operation pairs a PostgreSQL query with a MinIO HTTP transfer (\texttt{put\_object}/\texttt{get\_object}).},label={lst:pm}]
-- Schema: as Postgre, but the image is replaced by a MinIO object key
CREATE TABLE sensor_media (
  sample_id BIGSERIAL NOT NULL, device_id BIGINT NOT NULL, ts TIMESTAMPTZ NOT NULL,
  minio_object_key TEXT NOT NULL, payload_size_bytes INTEGER NOT NULL,
  width INTEGER, height INTEGER, mime_type TEXT NOT NULL,
  PRIMARY KEY (ts, sample_id));
SELECT create_hypertable('sensor_media', by_range('ts'));
CREATE INDEX idx_device_ts_desc ON sensor_media (device_id, ts DESC);

-- Insert: upload the image to MinIO (HTTP PUT), then store only its key in Postgre
minio.put_object(bucket, key, image_bytes, length, content_type);  -- HTTP PUT
INSERT INTO sensor_media (device_id, ts, minio_object_key, payload_size_bytes, ...)
VALUES (%s, %s, %s, %s, ...);

-- Bulk retrieval: read the keys in a time range, then stream each object from MinIO
SELECT ts, minio_object_key FROM sensor_media
WHERE device_id = %s AND ts >= %s AND ts <= %s ORDER BY ts;
-- for each key:  minio.get_object(bucket, key)                    -- HTTP GET

-- Latest-frame read: newest key from Postgre, then a single object fetch
SELECT ts, minio_object_key FROM sensor_media
WHERE device_id = %s ORDER BY ts DESC LIMIT 1;
-- then:  minio.get_object(bucket, key)                            -- HTTP GET
\end{lstlisting}

\end{appendices}

\bibliography{references}

\end{document}
