Choosing Between FL, MPC, and DP for Spatial Pipelines
Selecting a privacy technology for a geospatial pipeline is a routing decision driven by a handful of concrete inputs, not a survey of mechanisms. This guide is a decision framework: feed it where raw coordinates are allowed to live, who is trusted at the output boundary, whether you are releasing a statistic, training a model, or computing a joint function, and it returns exactly one of differential privacy, federated learning, secure multi-party computation, a composed FL + DP-SGD + SecAgg stack, or a hardware enclave — each bound to the parameter that makes it real. It sits under the privacy model comparison guide within Core Fundamentals & Architecture for Spatial Privacy, and it bridges the three implementation sections — federated learning workflows for geospatial data, secure multi-party computation in spatial analytics, and Differential Privacy for Geospatial Data — by telling you which one a given pipeline actually needs before you open any of them. The parent guide ranks the mechanisms on trust, utility, and cost; this page turns that ranking into an executable decision procedure.
Decision Inputs and Calibration
The framework consumes six signals. Each is a yes/no or small-enumeration fact about the pipeline, and each moves the routing deterministically. Gather them before you evaluate any mechanism; guessing here is where most mis-selections start.
- Raw-data locality. Can raw coordinates legally and operationally sit in one place behind a trusted curator? If yes, a noisy release is enough and you never pay for cryptography. If no — HIPAA patient mobility that cannot leave a hospital silo, GLBA customer routing across mutually distrustful banks — the compute must travel to the data, which rules DP-on-centralized-data out immediately.
- Adversary at the output boundary. Is the party receiving results trusted? A trusted internal analyst tolerates the central mechanism; an untrusted downstream consumer forces perturbation at the source. This is the split worked in depth in comparing central vs local differential privacy for GIS, and it changes only which DP you use, not whether DP is the answer.
- What you are computing. Releasing a statistic (a density heatmap, an origin–destination count), training a model (mobility prediction, on-device routing), or evaluating a joint function two parties both need (private set intersection, encrypted proximity) are three different problems that route to DP, FL, and MPC respectively.
- Server trust in aggregation. When training is federated, is the aggregation server honest-but-curious? A semi-honest server can reconstruct an individual client’s gradient from a plaintext update, so it forces secure aggregation and per-round noise on top of FL.
- Exactness versus throughput. A joint function that must be exact at high query volume may not tolerate MPC’s bandwidth and round latency; an attested hardware enclave computes in the clear inside sealed memory at near-native speed, trading a cryptographic assumption for a hardware one.
- Utility budget. The tolerable spatial error —
< 50 mfor epidemiological clustering,< 10 mfor dispatch — sets the floor for DP and theL2clip norm for DP-SGD, and it is the tiebreaker when two mechanisms both satisfy the trust constraint.
The table condenses the routing. Read it top to bottom: the first row that constrains your pipeline usually decides the mechanism, and the later rows tune it.
| Input signal | Concrete question | Routes toward | Governing knob |
|---|---|---|---|
| Raw-data locality | Can a trusted curator hold raw coordinates? | yes → DP; no → FL / MPC / TEE |
trust-boundary definition |
| Computation type | Statistic, model, or joint function? | statistic → DP; model → FL; joint function → MPC | — |
| Server trust (FL) | Is the aggregation server semi-honest? | yes → FL+DP+SecAgg; no → FL |
noise multiplier, SecAgg quorum |
| Output adversary | Is the analyst untrusted? | central DP vs local DP | per-report split |
| Exactness + throughput | Exact result at high QPS? | attested HW → TEE; else → MPC | enclave attestation, t-of-n |
| Utility budget | Tolerable spatial error? | tightens , clip norm | , L2 |
How the mechanisms compose
The five outputs are not mutually exclusive; the framework returns a primary mechanism, and two of them routinely stack. Federated training composes with DP-SGD and SecAgg so that a semi-honest server sees only a masked sum of clipped, noised gradients — the composition the FL+DP+SecAgg leaf names, with masking mechanics covered under the federated learning workflows section. MPC composes as a substrate for aggregation: an MPC-backed secure sum replaces the trusted aggregator in FL, or computes the joint function whose only output is then perturbed. And DP is a post-processing overlay on any of them — because any deterministic function of a DP release stays DP, you can layer a final Laplace or Gaussian mechanism on an MPC or FL output to bound what the released statistic itself leaks, drawing noise at scale . The rule of thumb: MPC and TEE decide who may see the inputs, FL decides whether raw data moves, and DP decides what the output leaks — so a hardened pipeline often answers all three.
Reference Implementation
The function below encodes the tree exactly. It takes a plain requirements dict (so it can be driven from a config file or an intake form), validates it into a typed PrivacyRequirements dataclass, and returns one of the five model labels. The Recommendation it produces internally carries a rationale string for the audit log; recommend_privacy_model returns just the routed label so callers and tests can branch on it. Comments mark the lines where a signal has a privacy consequence.
from __future__ import annotations
from dataclasses import dataclass
from typing import Literal
OutputType = Literal["statistic", "model", "joint_function"]
ModelLabel = Literal["DP", "FL", "MPC", "FL+DP+SecAgg", "TEE"]
@dataclass(frozen=True)
class PrivacyRequirements:
"""The six routing signals, gathered before any mechanism is evaluated."""
raw_may_be_centralized: bool # can a trusted curator hold raw coords?
output_type: OutputType # what is actually computed
server_semi_honest: bool = False # FL aggregator is honest-but-curious
untrusted_analyst: bool = False # output consumer is not trusted
hardware_enclave_available: bool = False # attested TEE on the compute nodes
throughput_bound: bool = False # exact result needed at high QPS
def __post_init__(self) -> None:
if self.output_type not in ("statistic", "model", "joint_function"):
raise ValueError(f"unknown output_type: {self.output_type!r}")
@dataclass(frozen=True)
class Recommendation:
model: ModelLabel
rationale: str
def _decide(req: PrivacyRequirements) -> Recommendation:
"""Deterministic mechanism routing — mirrors the decision-tree diagram."""
# Q1: a trusted curator may hold raw data -> perturb the release, skip crypto.
if req.raw_may_be_centralized:
variant = "local DP at source" if req.untrusted_analyst else "central DP"
return Recommendation(
"DP",
f"Raw data may be centralized; release a noisy statistic via {variant} "
f"(scale b = sensitivity / epsilon).",
)
# Raw data is pinned to the device/silo: computation must come to the data.
if req.output_type == "model":
# Q4: a semi-honest server can reconstruct a single client's gradient,
# so mask it (SecAgg) and add per-round noise (DP-SGD) on top of FL.
if req.server_semi_honest:
return Recommendation(
"FL+DP+SecAgg",
"On-device training with a semi-honest aggregator: federated "
"learning, DP-SGD clipping/noise, and SecAgg masking composed.",
)
return Recommendation(
"FL",
"On-device training, no raw sharing, trusted aggregator: plain "
"federated averaging with an L2 clip norm.",
)
# A joint function / exact result over inputs that can never be centralized.
# Q6: attested hardware trades a crypto assumption for a hardware one.
if req.hardware_enclave_available and req.throughput_bound:
return Recommendation(
"TEE",
"Exact joint compute at high throughput over inputs that cannot be "
"centralized: sealed computation in an attested enclave.",
)
return Recommendation(
"MPC",
"Mutually distrustful parties need an exact joint function and no party "
"may see another's raw input: secret-shared secure computation.",
)
def recommend_privacy_model(requirements: dict) -> str:
"""Route a spatial pipeline to one of DP / FL / MPC / FL+DP+SecAgg / TEE.
Returns the model label; the rationale is emitted for the audit trail so a
reviewer can trace the choice back to the requirement that forced it.
"""
rec = _decide(PrivacyRequirements(**requirements))
print(f"[privacy-router] {rec.model}: {rec.rationale}") # audit line
return rec.model
Validation Checkpoint
Mis-routing is silent — the wrong mechanism still runs and still produces plausible output — so the canonical scenarios must be asserted in CI. Each assertion below pins one path through the tree to its expected label; if a later edit to _decide reorders the branches, exactly one of these fails.
def _validate() -> None:
# 1. Untrusted-analyst statistical release -> DP (local variant at source).
assert recommend_privacy_model({
"raw_may_be_centralized": True,
"output_type": "statistic",
"untrusted_analyst": True,
}) == "DP"
# 2. Two mutually-distrustful providers computing a joint function -> MPC.
assert recommend_privacy_model({
"raw_may_be_centralized": False,
"output_type": "joint_function",
}) == "MPC"
# 3. On-device model training, no raw sharing, trusted server -> FL.
assert recommend_privacy_model({
"raw_may_be_centralized": False,
"output_type": "model",
"server_semi_honest": False,
}) == "FL"
# 4. Same, but a semi-honest server -> compose FL + DP-SGD + SecAgg.
assert recommend_privacy_model({
"raw_may_be_centralized": False,
"output_type": "model",
"server_semi_honest": True,
}) == "FL+DP+SecAgg"
# 5. Exact joint function at high throughput with attested hardware -> TEE.
assert recommend_privacy_model({
"raw_may_be_centralized": False,
"output_type": "joint_function",
"hardware_enclave_available": True,
"throughput_bound": True,
}) == "TEE"
# 6. An unknown output_type must fail loudly, never route by default.
try:
recommend_privacy_model({"raw_may_be_centralized": True,
"output_type": "raster"})
except ValueError:
pass
else:
raise AssertionError("unknown output_type must raise")
print("all routing invariants hold")
if __name__ == "__main__":
_validate()
Incident Response and Edge Cases
Every failure below is a mis-selection that survives testing because the chosen mechanism still runs — the damage is a privacy gap, not a crash.
- DP chosen where raw data crossed a silo boundary. The team routed to central DP because the output looked like a statistic, but the “curator” was actually two distinct legal entities pooling raw pings — so raw coordinates crossed a trust boundary in cleartext before any noise was added. The DP guarantee covers only the release, not the pooling. Remediation: re-run the framework with
raw_may_be_centralized=False; the joint origin–destination count belongs on the MPC path, with DP layered on the reconstructed aggregate, not the raw join. - Plain FL against a semi-honest server. FL was selected correctly for on-device training, but
server_semi_honestwas left at its defaultFalsefor a cloud aggregator the operator does not fully control. The server observes each client’s clipped gradient and inverts it back toward a home location. Remediation: flip the signal toTrueso the router returnsFL+DP+SecAgg; the masked sum and per-round noise are what actually protect the update, not the fact that raw pings never left the phone. - MPC where a TEE was needed (or the reverse). A real-time proximity join was routed to MPC; the round-trip latency blew the SLA, and analysts began bypassing it to the raw path — the worst possible outcome. Remediation: if attested hardware is available and the workload is throughput-bound, route to TEE; if it is not, keep MPC but add a circuit breaker that serves elevated-noise pre-aggregated tiles under load rather than exposing raw geometry. Never let a slow privacy path push traffic to no path.
- Composition ignored, budget double-spent. A model was trained under FL and a tabular heatmap released under DP from the same dataset, each against its own ceiling. Together they leak more than either bound admits. Remediation: the framework’s primary label does not absolve you of accounting — debit one shared, durable ledger across the FL release and the DP release, and fail closed when it is unreachable.
Frequently Asked Questions
Does a real pipeline ever need more than one of FL, MPC, and DP at once?
Frequently. The framework returns a primary mechanism, but the three compose along different axes: FL decides whether raw data moves, MPC or a TEE decides who may see the inputs, and DP decides what the final output leaks. A common hardened stack is FL for training, SecAgg (an MPC-style masked sum) for aggregation, and DP-SGD noise on the update — the composed FL+DP+SecAgg leaf. Whenever two mechanisms touch the same subjects, they must also share one privacy-budget ledger.
If raw data can be centralized, why would I ever pick MPC or FL?
You would not, purely for privacy. Once a trusted curator can legally and operationally hold raw coordinates, a calibrated DP release gives the highest spatial utility at the lowest cost, and cryptography buys nothing. FL and MPC earn their overhead only when raw data cannot be centralized — a hard silo boundary, mutually distrustful parties, or a regulation that forbids the pooling itself. The first question in the tree exists precisely to stop teams from paying for MPC when a curator boundary already holds.
How does the framework choose between MPC and a trusted execution environment for a joint function?
Both keep parties from seeing each other's raw inputs, so the tiebreaker is exactness-at-throughput versus trust assumption. MPC needs no special hardware but pays in bandwidth and round latency; a TEE computes in the clear inside sealed, attested memory at near-native speed but asks you to trust the hardware vendor's enclave and attestation chain. Route to TEE only when the workload is throughput-bound and attested enclaves are actually available; otherwise MPC's cryptographic guarantee is the safer default.
Where does an untrusted analyst change the answer within DP?
It changes central versus local DP, not whether DP is chosen. A trusted analyst tolerates a central mechanism, where a curator perturbs once after aggregating and the same epsilon buys low variance. An untrusted output consumer forces perturbation at the source under local DP, whose variance scales with the inverse square of epsilon. The framework returns DP either way; the untrusted_analyst signal only selects the variant and the epsilon split.
Related
- Privacy model comparison — the parent guide that ranks these mechanisms on trust, utility, and cost.
- Comparing central vs local differential privacy for GIS — the DP sub-decision this framework defers to the untrusted-analyst signal.
- Federated learning workflows for geospatial data — the FL and FL+DP+SecAgg path in depth.
- Secure multi-party computation in spatial analytics — the MPC and TEE path for joint compute over private inputs.
- Differential Privacy for Geospatial Data — the DP overlay that bounds what any output leaks.
Up: Privacy model comparison · Core Fundamentals & Architecture for Spatial Privacy