Measure Once, Model Everywhere:
Model-Based Per-Request Resource Consumption for HTTP
June 01, 2026
Recent proposals for HTTP-based sustainability disclosure focus on what environmental information should be transmitted at the protocol boundary, for example through response headers, but leave open the practical question of how such per-request values can be generated in realistic deployments. This paper addresses that implementation gap. We present a model-based approach for estimating resource consumption and \(CO_2e\) per HTTP request without requiring fine-grained production power telemetry. The approach benchmarks endpoints offline under controlled conditions, derives compact endpoint-specific energy models from observable request features, and evaluates these models online at the HTTP server boundary. We implement this mechanism as an nginx extension that loads a JSON model registry and emits per-request metadata for energy, grid intensity, embodied emissions, and total request-level impact. We show that heterogeneous request classes can be represented with constant, linear, and piecewise models, and that the same approach extends to endpoints whose dominant cost driver is only visible at the application layer through inputs such as token counts. Our evaluation indicates that the approach is operationally feasible and introduces only low runtime overhead.
Software is increasingly delivered through HTTP interfaces built on opaque stacks of virtualised infrastructure, managed platforms, and third-party services. The dominant cloud-native model presents these resources as elastic and available on demand: compute, storage, and bandwidth can be acquired through a single API call or a dashboard click, with billing and quotas as the primary feedback channels. The same abstractions that make this delivery scalable also conceal the physical and ecological costs of operating the underlying infrastructure [1]–[3], so that at the interface where requests are issued the system appears practically limitless. Users can observe latency and price, but not the energy use or emissions of a single request. Providers face a similar challenge: even when disclosure is desired, request execution spans multiple systems, and fine-grained power telemetry is typically unavailable.
A recurring principle in sustainable computing is to expose information at the interface where decisions are made. The Software Carbon Intensity (SCI) specification expresses emissions relative to a functional unit \(R\) [4]. For web systems, the natural functional unit is the HTTP request. If request-level impact were available at the protocol boundary, clients could incorporate it into decisions such as retry behaviour, batching, or prompt design.
HTTP is a natural disclosure surface, and prior work has proposed response headers for communicating carbon information [5]–[8]. However, these efforts focus on what to disclose, not on how to derive per-request values in practice.
Per-request disclosure does not by itself reduce demand, but it is a precondition for the design strategies that do. Sufficiency- and sobriety-oriented approaches [9], [10], critiques of growth-oriented computing infrastructure [11], and low-impact server designs such as the solar website [12] all require the marginal environmental cost of an interaction to be legible at the boundary where the request is issued. Without that legibility, providers and clients cannot distinguish high-cost from low-cost interactions, and ecological cost remains structurally excluded from the design decisions that determine aggregate consumption.
This paper addresses the implementation gap by introducing a practical, model-based method for deriving per-request energy and emissions. Instead of relying on production telemetry, endpoints are benchmarked offline under controlled conditions to derive compact energy models that are then evaluated at request time using variables already observable at the HTTP boundary, such as request duration, transferred bytes, or application-level metadata. HTTP-based disclosure is used as one instantiation but is not required by the method.
This paper makes four contributions: (1) It separates the protocol-level question of what to disclose from the systems question of how to generate request-level values, and identifies the latter as a key gap in current HTTP sustainability discussions. (2) It proposes a measurement-to-model pipeline that derives compact, interpretable, and executable energy models for HTTP endpoints from controlled offline benchmarks. (3) It demonstrates how these models can be evaluated at the HTTP server boundary and exposed as request-level sustainability metadata, while keeping underlying assumptions explicit. (4) It evaluates the feasibility, expressiveness, and runtime overhead of the approach across heterogeneous endpoints, including conventional web services and an inference endpoint that serves as an example of an endpoint requiring application-supplied features.
Assessing the environmental impact of software requires more than raw instrumentation. Guldner et al.propose the Green Software Measurement Model (GSMM), which emphasises that sustainability assessment depends on explicit modelling choices, system boundaries, and the interpretation of measurements [13]. The Software Carbon Intensity (SCI) specification similarly frames impact relative to a functional unit \(R\) [4]. Together, these approaches highlight that measurement alone is insufficient and must be complemented by modelling.
Prior work also shows that energy use varies significantly with workload characteristics. Pärssinen et al.quantify the environmental impact of web interactions [2], and Sala et al.demonstrate that sustainability metrics can be integrated into operational web monitoring [14]. In the context of AI, Desislavov et al.and Poddar et al.show that inference energy depends on runtime properties such as execution time and output length [15], [16]. These works establish that fine-grained variation exists, but primarily analyse it offline or at aggregate levels.
Attributing energy and emissions in cloud environments is inherently difficult. Fair-CO2 highlights the challenge of allocating both operational and embodied emissions across shared infrastructure and multi-tenant systems [3]. This limits the availability of directly observable per-request values in production environments.
Recent work has explored HTTP as a surface for communicating sustainability information. Martin proposes a "Carbon-Emissions-Scope-2" response header [5], and more recent drafts define structured sustainability headers [8].
A parallel body of work argues that computing should be reconceived under non-negotiable ecological constraints rather than treated as a domain to be optimised within a growth-oriented status quo [9]–[11]. Several strands of this literature intersect directly with the present paper. Raghavan and Ma argue that the energetic and material substrate of the Internet must be made legible to system design rather than treated as an externality [17]. Mytton shows that standardised cloud reporting tends to hide rather than expose the emissions associated with computation, reinforcing the case for disclosure mechanisms that operate close to the unit of consumption [1]. Constraint-led design has also been demonstrated empirically: the solar-powered Low-tech Magazine website exposes its energy budget directly to readers and modulates content under poor solar conditions, treating available energy as a binding parameter of service behaviour rather than as an externality [12]. The method proposed in this paper is a direct substrate for these positions. Sufficiency and sobriety arguments require an interface at which the marginal cost of an interaction can be seen and compared; degrowth-oriented critiques require ecological cost to be inescapable at the point of demand rather than externalised through cloud abstractions; low-impact server designs (solar websites, low-tech publishing, intermittent computing) require operating envelopes that the underlying system can both honour and communicate. The mechanism developed here supplies that substrate without prescribing a specific level of consumption.
Existing work therefore establishes the need for modelling, demonstrates workload-level variation, and defines potential disclosure interfaces. However, it does not provide a practical method for generating per-request energy and emissions estimates under realistic deployment constraints. In particular, the step from controlled measurements to request-level values available at the interface remains insufficiently specified.
This section presents our approach for deriving per-request energy and emissions estimates from controlled measurements under realistic observability constraints. The approach separates offline measurement from online estimation: endpoints are characterised offline under controlled conditions, and the resulting models are evaluated at request time using variables observable at the HTTP boundary.1 A method addressing this setting must satisfy four design requirements: it must (i) operate under limited observability, including deployments without fine-grained power sensors; (ii) be efficient enough to evaluate on every request; (iii) remain interpretable, so that providers can communicate the assumptions underlying the reported values; and (iv) capture heterogeneous endpoint behaviour, from near-constant-cost CRUD (create, read, update, delete) requests to endpoints whose cost depends on request-specific inputs only visible at the application layer. A concrete instantiation of the method follows in Sections 4 and 5.
Each endpoint \(e\) is associated with a model \(\widehat{E}_e\) that predicts request energy from one or more observable features (e.g., request duration, transferred bytes, HTTP method, response status, request-specific parameters). The feature set is not fixed; it captures quantities that are either already available at the HTTP boundary or can be exposed with minimal application changes. We restrict the model space to a small set of families that balance expressiveness, interpretability, and efficient runtime evaluation. The full collection of fitted models, together with the per-deployment carbon parameters from Section 3.2, is stored as a registry: a compact data structure indexed by endpoint identifier that the server loads at runtime (Section 5).
Three patterns recur in practice: some endpoints show negligible variation across requests, others scale approximately with an observable feature, and some exhibit distinct scaling regimes that no single straight line fits well. We use one model family for each case.
Constant model. When energy does not vary appreciably with the input, a single representative value suffices. The endpoint is assigned a fixed predicted energy \(c_e\), set to the mean energy observed during calibration: \[\widehat{E}_e = c_e.\]
Linear model. When energy varies in proportion to an observable quantity, a linear model captures this scaling as a baseline plus a per-feature contribution. For a single feature \(x\), \[\widehat{E}_e(x) = \beta_0 + \beta_1\, x,\] where the intercept \(\beta_0\) is the baseline energy of a request and the coefficient \(\beta_1\) the additional energy per unit of \(x\). Further features can be incorporated by adding more \(\beta_j\, x_j\) terms. Coefficients are fitted to the calibration data by standard least-squares estimation.
Curve model. Some endpoints exhibit distinct scaling regimes, for example behaving as near-constant for small inputs and growing sharply for large ones. Rather than committing to a particular non-linear functional form, the curve model represents the endpoint by a small set of measured points, each pairing a feature value \(z_i\) with the energy \(E_i\) observed at that value. At request time, the predicted energy for an input \(z\) is obtained by linear interpolation between the two adjacent measured points. The model therefore reads as a sequence of straight-line segments through the calibration data: it is simple to evaluate while allowing the slope to change between regimes.
Application-supplied features. Some predictors are not visible at the HTTP server layer but are known to the application or a downstream runtime (e.g., token counts for inference, result-set cardinality, cache-hit indicators). Such quantities can be exposed to the server as request-scoped metadata via internal headers or server variables, and used as additional inputs to any of the three model families above.
Model family selection. Family assignment is treated as a modelling decision informed by workload-scaling benchmarks: energy is measured under controlled variation of the relevant workload parameter, and the family that best reflects the observed scaling is selected. Fitting then reduces to standard parameter estimation (averaging for constant models, least-squares for linear, retained support points for curves). The method does not preclude automated selection or uncertainty-aware fitting, but the present formulation makes the manual modelling step explicit so that the resulting registry remains inspectable.
The models above predict per-request energy. To obtain a sustainability metric that is comparable across deployments, we convert this energy into carbon emissions, distinguishing operational emissions (energy consumed during the request) from embodied emissions (a share of the hardware’s manufacturing impact). Reporting both components separately keeps the underlying assumptions visible at the boundary.
Operational emissions. Operational emissions are obtained by multiplying the predicted energy by the grid carbon intensity \(I\) at the time of execution: \[\widehat{C}^{op}_e = \widehat{E}_e \cdot I.\] The grid carbon intensity \(I\) is an input to the method, not a fixed property of it. The same equation supports two regimes. In the static regime, \(I\) is set to a representative value for the deployment region, for example a published annual or location-specific average, and the reported operational emissions correspond to that average. In the dynamic regime, \(I\) is refreshed at request time or on a short interval from an external signal such as a public carbon-intensity service (for example, Electricity Maps [18] or WattTime [19]) or an internal monitoring source; the reported value then reflects the grid state that applied while the request was served. In both regimes, the value of \(I\) used for the conversion is itself disclosed alongside the resulting emissions, so that downstream consumers can recover the assumption. Units (for example, \(\mathrm{mWh}\) for energy and \(\mathrm{gCO_2e/kWh}\) for intensity) are reconciled in the implementation.
Embodied emissions. Embodied emissions capture the carbon cost of manufacturing and provisioning the hardware. Following a time-based allocation, the total embodied emissions \(M\) of the system are amortised over an assumed operational lifetime \(T\) to give a constant embodied rate \(r^{emb} = M/T\). The share attributed to a request with processing time \(t\) is then \[\widehat{C}^{emb}_e = r^{emb} \cdot t.\] This is a simple and transparent allocation scheme. Other schemes, such as utilisation-weighted or capacity-based allocation, can be substituted depending on the deployment context [4], [20]–[22]; the rest of the method does not depend on this choice.
Total per-request emissions are the sum of the two components: \[\widehat{C}_e = \widehat{C}^{op}_e + \widehat{C}^{emb}_e.\]
Any concrete instantiation requires accounting choices, for example whether benchmark labels are derived from total machine energy or from idle-subtracted measurements (where the machine’s baseline idle energy is subtracted to isolate the request-dependent signal), whether protocol overhead is included in calibration, and how embodied carbon is allocated. These choices do not affect the structure of the equations above but do affect interpretation, and must therefore be disclosed alongside the reported values. The specific choices made in this paper are stated in Section 6; limitations are consolidated in Section 7.
This section instantiates the method of Section 3 on a concrete benchmark application. It describes how we generate per-request energy labels \(E\) (in \(\mathrm{mWh}\)) from controlled experiments. These measurements form the basis for fitting the per-endpoint energy models described in Section 3. For each request, we record energy at the machine boundary and associate it with request-level observations obtained during benchmarking, including request processing time, data transfer volume, and endpoint-specific workload parameters.
All measurements were executed using the Green Metrics Tool (GMT) [23] in a controlled measurement setup. Experiments were conducted on a dedicated machine to ensure reproducibility and minimise interference from background workloads.
We used the GMT “ML/AI Profiling” profile on a server-class system with the following configuration: an Intel Core i5-9600K @ 3.70 GHz (6 cores / 6 threads; Turbo enabled; DVFS enabled) with 32 GB of memory, an NVIDIA GeForce GTX 1080 (8 GB VRAM, CUDA 12.2, driver 535.274.02), power measurement via MCP39F511N and IPMI (as provided by GMT), running Ubuntu 24.04 (NOP Linux) [23].
Turbo boost and dynamic frequency scaling were left enabled to reflect typical deployment conditions.
To obtain stable energy measurements, we followed the Green Coding best practices for controlled benchmarking [24]. These practices stress that software-energy measurements are sensitive to noise and should therefore be performed under controlled conditions, with temperature effects, idle baselines, and run-to-run variance taken into account.
Concretely, we ran the service under test (SUT) on an isolated machine running NOP Linux, a minimal environment with non-essential processes disabled to reduce measurement noise. Before sampling, we warmed up the SUT to reach a steady state. We then recorded an idle baseline for a comparable interval. During the experiments, we varied one workload factor at a time, such as payload size or token count, and repeated each condition often enough to make the signal distinguishable from measurement noise. As recommended in the Green Coding documentation, the exact number of repetitions depended on the variance and expected signal strength of the endpoint under test.
The whole test suite was executed 10 times. All measurements are available under https://metrics.green-coding.io/runs.html?uri=https
We implemented a minimal REST-style ToDo application in Python that serves HTTP requests using SQLite as the backend database. A user can log in and log out, create ToDo items with a title, text, and optional file attachment, retrieve all ToDo items, and mark individual items as done. In addition, the application provides an LLM endpoint for sentence completion. The application and benchmark harness are publicly available [25]. While SQLite is a simple dependency, the GMT harness supports measuring more complex multi-service deployments. We use this application to cover a range of endpoint behaviours. The endpoints are described in Table 1.
| /login | Given a username and password returns an authenticated session cookie |
| /logout | Invalidates the authenticated session |
| /createToDo | Takes a title, text and attachment and creates a new "todo" item in the database |
| /done | Given a todo id marks it as done in the DB |
| /getToDos | Returns all the todos of the user |
| /deleteAllToDos | Deletes all the todos of the user |
| /ai | Given a text sends it to an LLM for autocompletion and returns the ai response |
HTTPS is excluded from the measurements to avoid entangling endpoint energy with TLS handshake and encryption overhead; the implications of this scoping choice and possible mitigations are discussed in Section 7.
Each endpoint was benchmarked with a workload script designed to expose its expected scaling factors. Stateful endpoints were called with a pre-acquired session cookie reused across runs to avoid repeatedly measuring login overhead. Repetition counts
are chosen per endpoint: 100 calls per condition for the lightweight REST endpoints (/login, /logout, /createToDo, /getToDos, /done), where single-request energy is too small to resolve above
measurement noise; and 10 calls per prompt profile for /ai, where each inference call is long enough to produce a measurable signal on its own. /createToDo conditions vary either text length (100, 1 000, 10 000, 100 000 chars) or
attachment size (1 KB, 10 KB, 100 KB, 1 MB, 5 MB); /getToDos and /done run against the populated state; /deleteAllToDos cleans up between conditions.
The /ai endpoint serves gemma3:1b via a local ollama container on the same machine. Inference behaviour is stabilised by downloading the model before sampling, prewarming caches, and holding decoding settings
constant. We treat prompt-token and generated-token counts as the application-supplied features for /ai (Section 3.1): the application layer reads them from the inference runtime and exposes them as
response-scoped metadata, so a token-linear model can be fitted without GPU telemetry. Prior work supports this choice: under fixed serving conditions, latency and energy scale approximately with output-token count [16], [26], [27]. The inference endpoint is included as an example of a workload whose dominant cost driver is only visible at the application layer; we make no claim about hosted inference services at scale, where a substantial share
of emissions occurs outside the reverse-proxy boundary.
We derive per-request energy labels \(E\) (in \(\mathrm{mWh}\)) from machine-level energy measurements collected during benchmarking [28]. For each condition, we compute: \[E = \frac{E_{\text{machine}}}{n},\] where \(E_{\text{machine}}\) is the total energy measured during the benchmark interval and \(n\) is the number of requests executed in that interval.
This yields an average per-request estimate that approximates the energy attributable to the endpoint under the given workload condition. The estimate assumes that requests within each condition are homogeneous and that background effects remain stable during the measurement interval.
We verify that energy varies consistently with the controlled workload parameter under input sweeps, indicating that the derived labels capture the intended endpoint behaviour.
For each measured request, we associate the energy label \(E\) with features that are available (or can be made available at low cost) at the HTTP server boundary. The features below were selected on two criteria: that
they can be measured at the boundary without invasive instrumentation, and that they vary meaningfully across the requests of interest. Headers such as Content-Type are intentionally omitted because in this case study, as is typical for
REST-style services, they are effectively fixed per endpoint and method, and therefore do not provide additional discriminating signal beyond what endpoint identity and HTTP method already carry.
Processing time \(t\): request handling time as observed by the reverse proxy (e.g., nginx $request_time-style timing variables).
Request and Response bytes \(b^{req}\), \(b^{res}\): the size of incoming and outgoing data, capturing transfer-related effects.
HTTP method \(m\): the request method (e.g., GET, POST, PUT, DELETE), which helps distinguish different execution paths and backend
behaviours.
Response status \(r\): captures outcomes such as success, redirection, rejection, or failure, which may correlate with different execution costs.
URL-parameter-derived features \(q\): selected information derived from the request URI, such as the presence of specific query parameters, total query-string length, parameter count, or whitelisted numeric values (e.g., pagination limit). We use derived features rather than raw query strings in order to avoid unnecessary sparsity and high-cardinality model inputs.
Token count \(\tau\): for AI inference, prompt and generated token counts exposed by the application.
The resulting dataset is a collection of tuples \((e, x, E)\) per endpoint \(e\), where \(x\) is the vector of relevant features. We then fit the constant, linear, and piecewise curve models described in Section 3, and export the fitted parameters as will be described in the next section.
We realise per-request estimation and disclosure as an nginx extension built on the ngx_http_js_module (using the njs runtime), which avoids kernel modifications or external telemetry interfaces.
At startup, the module loads the JSON registry described below and normalises it once per worker: routes are canonicalised, coefficients preloaded, and curve support points sorted. For each request, the module resolves the matching endpoint, optionally narrows the variant by HTTP method, extracts the required input features from variables already exposed by nginx (request time, request and response sizes, and, where applicable, application-supplied metadata such as token counts), and evaluates the model. Constant models return a fixed value; linear models apply preconfigured coefficients; curve models interpolate between precomputed support points. The energy estimate is then converted to operational and embodied emissions using the configured carbon parameters and exposed via response headers; values can optionally be written to structured logs for downstream analysis.
The JSON registry defines how endpoint-specific energy models and their parameters are represented for runtime evaluation. At the top level, the registry is a map from endpoint identifiers (e.g., URI paths or location blocks) to per-endpoint
configuration objects. Each such object contains an energy_model plus the shared parameters needed later for emission calculations, namely grid intensity and the embodied-allocation rate. The energy_model itself is a tagged
structure whose fields depend on the chosen model family: constant models store a single value, linear models store an intercept and coefficients, and curve models store support points together with interpolation rules. The registry format also allows
multiple model variants for the same URL path, distinguished by an optional filter object. This is useful when, for example, GET and POST requests share the same endpoint path but exhibit different behaviour and
should therefore be matched to different energy models. Listing [lst:json-registry] does not show the full generated registry, but a compact excerpt with
representative instances of the model families used in the prototype.
Listing lst:json-registry: Excerpt from the JSON model registry with representative endpoint entries
{
"/ai": {
"filter": { "method": "POST" },
"energy_model": {
"kind": "linear",
"intercept_mWh": 7.062,
"prompt_token_coeff_mWh_per_token": 0.017,
"generated_token_coeff_mWh_per_token": 0.483
},
"embodied_rate_gCO2e_per_s": 0.001,
"grid_intensity_gCO2e_per_kWh": 121.111
},
"/done": {
"energy_model": {
"kind": "constant",
"value_mWh": 0.085
},
"embodied_rate_gCO2e_per_s": 0.001,
"grid_intensity_gCO2e_per_kWh": 121.111
},
"/getToDos": {
"energy_model": {
"kind": "curve",
"input": "data_size",
"points": [[49421.59, 0.072], [231310.93, 0.112], [2051378.03, 0.125], [20298823.13, 0.553]],
"interpolate": "linear",
"extrapolate": "linear_tail"
},
"embodied_rate_gCO2e_per_s": 0.001,
"grid_intensity_gCO2e_per_kWh": 121.111
},
...
}Energy is expressed in \(\mathrm{mWh}\); grid intensity in \(\mathrm{gCO_2e/kWh}\); embodied emissions as a time-based rate in \(\mathrm{gCO_2e/s}\), so per-request embodied impact follows from request duration. The grid-intensity field can be written statically or rewritten by a side process (e.g., fetching from Electricity Maps [18] or WattTime [19]); the registry is reloaded on configuration reload, so no nginx restart is required.
The computed values are exposed via response headers, separating the underlying components of the calculation rather than encoding everything in a single aggregated value. This keeps the modelling assumptions explicit at the boundary:
Request-Energy: per-request energy, in \(\mathrm{mWh}\).
Grid-Intensity: grid intensity in \(\mathrm{gCO_2e/kWh}\).
Request-Embodied-CO2e: embodied share allocated to the request, in \(\mathrm{mgCO_2e}\).
Request-SCI: total per-request emissions, in \(\mathrm{mgCO_2e}\).
These fields illustrate one possible design and are not proposed for standardisation. Listing [lst:curl] shows an example response with the four headers emitted (unrelated headers omitted for brevity).
Listing lst:curl: Example response headers emitted by the prototype nginx module
$ curl -sS -D - -o /dev/null \;
-X POST "http://localhost:8080/login" \;
-H "Content-Type: application/json" \;
-d "{\"username\":\"$USERNAME\",\"password\":\"$PASSWORD\"}"
HTTP/1.1 200 OK
Server: nginx/1.25.5
...
Set-Cookie: csrftoken=xxx; ...
Set-Cookie: sessionid=xxx; ..
(*@{\bfseries\ttfamily Request-Energy: 4.038}@*)
(*@{\bfseries\ttfamily Grid-Intensity: 121.111}@*)
(*@{\bfseries\ttfamily Request-Embodied-CO2e: 0.143}@*)
(*@{\bfseries\ttfamily Request-SCI: 0.633}@*)We evaluate the approach as a feasibility study: the benchmark suite was executed ten times to stabilise the measurements, after which we inspect the derived model parameters, perform one trace-based replay validation against an independent click-through workload, and compare paired runs with and without header emission to quantify overhead. The results support claims about operational plausibility and order-of-magnitude agreement, not a full statistical characterisation of model error across deployments.
We convert the GMT export into the JSON registry of Listing [lst:json-registry], instantiating all three model families. Family assignment was driven by
workload-scaling benchmarks: for example, we issued between 1 and 1000 calls to /login to confirm that per-request energy remained stable [29]. /login, /logout, /done, and /deleteAllToDos produced near-constant profiles and use constant models;
/createToDo and /getToDos showed payload-dependent scaling and use curve models with measured support points and piecewise-linear interpolation; /ai uses a least-squares linear model over an intercept plus prompt- and
generated-token counts.
For the measured system, grid intensity is configured statically at \(\num{121.111}\,\mathrm{gCO_2e/kWh}\) and the embodied allocation rate at
\(\num{0.001}\,\mathrm{gCO_2e/s}\); in production, the intensity could be refreshed from Electricity Maps [18] or WattTime [19] (Section 3.2). The registry is derived from total machine
energy rather than idle-subtracted measurements, and HTTPS/TLS overhead is excluded from the calibration; both choices are limitations discussed in Section 7.
| Endpoint / condition | Requests | |
| (mWh/req) | ||
| /login | 100 | 4.038 |
| /logout | 100 | 0.006 |
| /done | 100 | 0.085 |
| /deleteAllToDos | 100 | 2.835 |
| /getToDos (100 items) | 100 | 0.072 |
| /getToDos (1 000 items) | 100 | 0.112 |
| /getToDos (10 000 items) | 100 | 0.125 |
| /getToDos (100 000 items) | 100 | 0.553 |
| /createToDo (text, 100 chars) | 100 | 0.064 |
| /createToDo (text, 1 000 chars) | 100 | 0.079 |
| /createToDo (text, 10 000 chars) | 100 | 0.035 |
| /createToDo (text, 100 000 chars) | 100 | 0.096 |
| /createToDo (file, 1 KB) | 100 | 0.058 |
| /createToDo (file, 10 KB) | 100 | 0.061 |
| /createToDo (file, 100 KB) | 100 | 0.080 |
| /createToDo (file, 1 MB) | 100 | 0.288 |
| /createToDo (file, 5 MB) | 100 | 0.989 |
| /ai (very short prompt) | 10 | 29.978 |
| /ai (short prompt) | 10 | 251.044 |
| /ai (medium prompt) | 10 | 299.771 |
| /ai (long prompt) | 10 | 229.718 |
| /ai (very long prompt) | 10 | 274.852 |
We evaluate the fitted models across the different endpoint classes in the benchmark to assess whether they preserve the expected workload-dependent behaviour. We distinguish endpoints by whether their dominant cost driver is visible at the HTTP boundary or only at the application layer: the conventional CRUD-style endpoints fall in the first group, while the inference endpoint serves as an example of the second. Figure 1 summarises the fitted models for one representative endpoint from each group.
The generated registry shows that the REST endpoints fall into distinct behavioural classes. Authentication-related requests are close to constant cost. The fitted /logout model is only 0.006 mWh per request, while /login is
substantially larger at 4.038 mWh, reflecting additional work such as credential verification and cryptographic session establishment. The /done endpoint is also effectively constant, with a fitted value of 0.085 mWh per request across all
measured conditions.
In contrast, the payload-dependent endpoints exhibit clear scaling behaviour. For /createToDo, the fitted curve (Figure 1, left) remains nearly flat for small text-only requests but increases sharply once
file uploads become large. A request with a short text body requires about 0.064 mWh, while the 5 MB attachment condition reaches 0.989 mWh, corresponding to more than a fifteen-fold increase. Intermediate file sizes (1 KB, 10 KB, 100 KB, 1 MB) produce a
consistent progression, indicating that the curve model captures a meaningful size effect rather than measurement noise.
For /getToDos, the fitted model scales with the size of the returned collection. The smallest measured response proxy is approximately 49.4 kB and corresponds to 0.072 mWh per request, while the largest condition reaches about 20.3 MB and
0.553 mWh. This shows that response-size observables available at the HTTP boundary are sufficient to approximate workload-dependent behaviour without access to internal database operations.
These results illustrate that the fitted models capture the dominant differences between endpoint classes while remaining compact. The goal is not to reproduce the full internal behaviour of each endpoint, but to provide interface-level abstractions that preserve the major decision-relevant distinctions between small and large requests.
The inference endpoint is used here as a test of whether the method extends to endpoints whose dominant cost driver is not visible at the HTTP boundary. Such endpoints require application-supplied features in addition to, or instead of, server-level
observables; in this case, prompt-token and generated-token counts produced by the inference runtime. The observation that motivates this is that, when considering only prompt-profile labels (very-short, short,
medium, long, very-long), the observed runtimes are not strictly monotonic. In our measurements, the medium profile took longer than the very-long profile, which appears inconsistent with the
expectation that longer prompts should require more work.
This behaviour is explained by the underlying token statistics. While prompt-token counts increase monotonically across profiles (from roughly 20 to about 1010 tokens), generated-token counts vary substantially and do not follow the same ordering. In
this measurement, average generated-token counts were approximately 46.4 (very-short), 505.8 (short), 600.7 (medium), 446.5 (long), and 518.4 (very-long). As a result, prompt categories alone
are not reliable predictors of runtime or energy.
Using token-level information, the fitted model for /ai is given by \[\widehat{E}_{ai}(\tau^{prompt}, \tau^{gen}) =
7.062 + 0.017 \cdot \tau^{prompt} + 0.483 \cdot \tau^{gen}.\] The coefficients make the relative contribution of the two factors explicit. The weight assigned to generated tokens is roughly 28 times larger than that of prompt tokens, indicating that
the dominant marginal work occurs during token generation rather than prompt processing. This is consistent with the behaviour of decoder-style inference systems. The right-hand panel of Figure 1 plots predicted against
measured per-request energy for all five prompt profiles; predictions agree with measurements to within approximately 1 mWh per condition, indicating that prompt-token and generated-token counts together explain almost all of the observed variation across
the benchmarked workload.
This result demonstrates that the application-supplied feature mechanism is necessary rather than optional: for endpoints in this class, HTTP-level observables such as payload size or coarse prompt labels are insufficient to capture the dominant cost driver. The inference endpoint here is one example of this pattern; other endpoints whose work depends on application-internal variables (for example, result-set cardinality, cache state, or downstream service invocations) can be accommodated by the same mechanism. We make no broader claim about the carbon footprint of inference services at scale; the demonstration here is confined to the locally served endpoint in this case study.
To assess how well the fitted endpoint models generalise beyond the isolated benchmark conditions used for calibration, we executed an additional no-header validation run that repeated a realistic user click-through path 100 times [30]. Each iteration performed the sequence /login \(\rightarrow\)
/deleteAllToDos \(\rightarrow\) /createToDo \(\rightarrow\) /getToDos \(\rightarrow\) /done \(\rightarrow\) /getToDos \(\rightarrow\) /logout, resulting in 700 HTTP requests in total. The total run was measured ten times with Green Metrics Tool to obtain the
machine-level reference energy and, independently, nginx access logs were replayed offline through the derived registry to obtain the model-based estimate.
The GMT reported a total machine energy of 597.18 mWh (\(\pm\) 0.74 %, average \(\pm\) standard deviation over all runs) [31], while the offline log replay produced an estimated total of 611.101 mWh. This corresponds to an absolute deviation of 13.921 mWh, or 2.33 % relative to the measured total. For an endpoint model derived from separate controlled measurements and then evaluated only from runtime-visible log features, this level of agreement is encouraging: the estimate preserves the correct order of magnitude and remains close enough to support relative comparisons and aggregate observability.
We evaluate runtime overhead using ten repeated-run comparisons with the nginx module disabled [32] and enabled [33]. Across the full run, mean machine energy rises from \(5325.07 \pm 0.48\%\) to \(5349.55 \pm 0.50\%\,\mathrm{mWh}\), an overhead of 0.46 % (from the total-runtime entry of the GMT comparison export).
Per-route data is shown in Tables 3–5. The differences are small and dominated by run-to-run variation. /login, the largest condition, changes by
−0.3 %. /logout appears to rise 10.9 %, but at 15 mWh per condition with standard deviations near 18 % this is better read as noise. For /getToDos and /done the changes range from roughly \(-4\) to \(+10\) percent across conditions; for /createToDo from \(+0.1\) to \(+11.1\) percent, with the largest
relative differences on the smallest absolute conditions. The practically relevant 1 MB and 5 MB uploads change by 0.2 % and 0.1 %.
We do not tabulate the AI endpoint: across the five prompt profiles, mean energy differences remained within \(\pm 1\) percent and runtime changes within \(0.3\) percent, indistinguishable from inference variability. Overall, per-request model evaluation and disclosure can be integrated at the HTTP server with low overhead.
| Class | Variant | ||
| (mWh) | |||
| (mWh) | |||
| Constant | No Header | 678.59 \(\pm\) 0.88% | 14.42 \(\pm\) 18.44% |
| Header | 676.31 \(\pm\) 0.95% | 15.99 \(\pm\) 17.26% | |
| \(\Delta\) | -0.3% | +10.9% |
| (chars) | Variant | |||
| (mWh) | ||||
| (mWh) | ||||
| (mWh) | ||||
| 100 | No Header | 37.68 \(\pm\) 5.74% | 20.99 \(\pm\) 5.49% | 34.35 \(\pm\) 14.57% |
| Header | 39.33 \(\pm\) 8.94% | 20.21 \(\pm\) 7.29% | 37.82 \(\pm\) 9.90% | |
| \(\Delta\) | +4.4% | -3.8% | +10.1% | |
| 1000 | No Header | 39.63 \(\pm\) 15.15% | 21.31 \(\pm\) 7.39% | 34.95 \(\pm\) 12.54% |
| Header | 43.16 \(\pm\) 10.45% | 21.71 \(\pm\) 6.67% | 33.49 \(\pm\) 13.69% | |
| \(\Delta\) | +8.9% | +1.9% | -4.2% | |
| 10000 | No Header | 42.48 \(\pm\) 10.15% | 30.26 \(\pm\) 4.15% | 39.41 \(\pm\) 9.45% |
| Header | 44.20 \(\pm\) 7.06% | 31.14 \(\pm\) 4.23% | 38.84 \(\pm\) 5.06% | |
| \(\Delta\) | +4.0% | +2.9% | -1.5% | |
| 100000 | No Header | 46.05 \(\pm\) 7.32% | 131.92 \(\pm\) 2.37% | 45.58 \(\pm\) 10.27% |
| Header | 48.82 \(\pm\) 7.45% | 131.35 \(\pm\) 1.90% | 49.35 \(\pm\) 8.72% | |
| \(\Delta\) | +6.0% | -0.4% | +8.3% |
3pt
| File size | Variant | |
| (mWh) | ||
| 1KB | No Header | 39.98 \(\pm\) 10.67% |
| Header | 41.42 \(\pm\) 15.37% | |
| \(\Delta\) | +3.6% | |
| 10KB | No Header | 36.27 \(\pm\) 9.13% |
| Header | 40.32 \(\pm\) 10.89% | |
| \(\Delta\) | +11.1% | |
| 100KB | No Header | 41.10 \(\pm\) 10.31% |
| Header | 44.73 \(\pm\) 10.08% | |
| \(\Delta\) | +8.8% | |
| 1MB | No Header | 68.66 \(\pm\) 3.17% |
| Header | 68.78 \(\pm\) 3.64% | |
| \(\Delta\) | +0.2% | |
| 5MB | No Header | 232.39 \(\pm\) 0.80% |
| Header | 232.62 \(\pm\) 0.97% | |
| \(\Delta\) | +0.1% |
We group limitations into four classes.
Modelling abstraction. Per-request estimates are interface-level abstractions, not exact physical attributions; they expose a consistent and decision-relevant signal rather than ground truth. The model reflects only the factors in the feature set, so unobserved effects (resource contention, background load, scheduling, co-tenancy, hardware-specific optimisations) can introduce systematic error. The current formulation does not emit uncertainty intervals; this limits the interpretation of absolute values but, as with latency and throughput, does not invalidate the signal for relative comparison.
Deployment dependence. Estimates depend on hardware generation, power management, virtualization, co-located workloads, and regional grid conditions. The same logical endpoint may exhibit different physical footprints across environments, and prediction error grows when the deployment diverges from the calibration setting. Periodic recalibration is therefore necessary; automating it on software releases or hardware changes is left to future work.
System boundary and attribution. A request may involve caches, databases, queues, or external services. The boundary here is the benchmarked deployment, which can include co-measured dependencies but not opaque third-party services. CDNs and other intermediaries shift where energy is expended, raising attribution questions (origin vs.edge). Whether reported values are marginal or include baseline must also be disclosed; the specific choices made here are stated in Section 6.
Prototype scope. HTTPS/TLS overhead is excluded from calibration; in deployments where HTTPS is mandatory it can be modelled as a separate constant or as a protocol-keyed variant. Family assignment is manual rather than automated. The
nginx integration uses ngx_http_js_module, which adds small but measurable interpretation overhead; a native C extension would improve this.
Beyond external disclosure, the approach also supports internal provider-side analytics. Software producers typically see request counts, latency, and cost but not the energy or emissions of their own endpoints. By combining offline-derived per-endpoint models with routine HTTP logs, providers can estimate and aggregate energy or \(\mathrm{CO_2e}\) across endpoints, customers, or time windows, even when the underlying infrastructure is opaque.
The case for disclosure as a precondition for constraint rests on an asymmetry: in current HTTP systems, clients and operators see latency, cost, and throughput but not environmental cost. This systematically excludes ecological considerations from the concrete software decisions that determine aggregate consumption. Making per-request impact visible does not, by itself, reduce demand; but it removes a structural barrier, since one cannot budget, cap, or differentially price what one cannot measure at the relevant granularity.
The mechanism is therefore best understood as a substrate for constraint-led design traditions rather than a substitute for them. Sufficiency-oriented practice [9], [10] requires that clients and providers can compare interactions and shift toward lower-impact alternatives, which presupposes a comparable per-request signal at the interface. Degrowth-oriented critiques of computing [11] require that the ecological cost of an interaction is inescapable at the point of demand rather than externalised through cloud abstractions that present resources as effectively unlimited [1]. Low-impact server designs in the tradition of the solar website [12] require operating envelopes that the underlying system can both honour and communicate; per-request impact gives such systems a concrete signal to expose to readers and clients. In each case, the contribution here is not a substitute for these strategies but the visibility layer they presuppose.
Three risks attach to disclosure of this kind. First, per-request values may be used for greenwashing: a provider could disclose small per-request numbers while aggregate demand grows unchecked. Second, the mechanism can shift responsibility asymmetrically, framing reduction as a client-side concern (“reduce your prompt length”) while infrastructure growth remains unquestioned. Third, quantification itself can naturalise the assumption that environmental impact is acceptable so long as it is accounted for. These risks do not invalidate the approach but they constrain the claims that can responsibly be made on it; the contribution is a reproducible, inspectable method for making environmental implications visible at the interface where decisions are made, not metrological certainty.
This paper argued that the missing piece in HTTP sustainability disclosure is not header-field semantics but a practical method for generating credible per-request values. We showed that controlled machine-level measurements can be transformed into compact endpoint models, stored in a JSON registry, and evaluated online at the HTTP boundary by an nginx-based prototype. The prototype represents heterogeneous endpoint classes, including both conventional CRUD routes and an AI inference endpoint, with low overhead.
What this makes visible is a precondition, not an end in itself. Per-request impact is a substrate for constraint-led design traditions, such as sufficiency and sobriety [9], [10], degrowth-oriented critiques [11], and low-impact server designs [12]. These traditions all assume that the ecological cost of an interaction is visible where demand is generated rather than externalised through cloud abstractions [1]. Visibility also carries hazards: per-request figures can greenwash undiminished growth, can shift responsibility onto clients while leaving infrastructure expansion unquestioned, and can naturalise the assumption that impact is acceptable so long as it is accounted for. We therefore offer this method not as metrological certainty but as a reproducible, inspectable way to bring ecological cost into the decisions where it currently has can not be considered. A natural next step is to re-implement the runtime path as a native nginx C extension, minimizing the interpretation overhead.
This work was funded by the Deutsche Bundesstiftung Umwelt (DBU).
/login workload-scaling benchmark (1–1000 calls).” Green Metrics Tool measurement run, 2026,
[Online]. Available: https://metrics.green-coding.io/stats.html?id=6c40a5b8-79b7-4372-a1c4-3ae7185451d2.