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 tree from raw-data locality, output trust, and computation type to a recommended privacy mechanism A top-down decision tree. The root question is whether raw coordinates can be centralized behind a trusted curator. A "yes" edge leads directly to a differential privacy leaf, where the choice of central versus local DP depends on whether the analyst is trusted. A "no" edge — raw data is pinned to the device or silo — leads to a question asking whether you are training a model. A "yes" leads to a question asking whether the aggregation server is only semi-honest: if so, the leaf is federated learning composed with DP-SGD and SecAgg; if the server is trusted, the leaf is plain federated learning. If you are not training a model but instead computing a joint function over inputs that can never be centralized, a further question asks whether you need attested-hardware throughput: if so the leaf is a trusted execution environment, otherwise the leaf is secure multi-party computation. Routing a spatial pipeline to one privacy mechanism yes no yes no yes no yes no Q1 · Raw data may be held by a trusted curator? Q2 · Training a model? Q4 · Aggregation server semi-honest? Q6 · Need attested hardware throughput? DP central curator, or local if the analyst is untrusted FL + DP-SGD + SecAgg honest-but-curious server FL no raw sharing; trusted aggregator MPC mutual distrust; exact joint result TEE attested enclave; high-throughput joins

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 m for epidemiological clustering, < 10 m for dispatch — sets the ε\varepsilon floor for DP and the L2 clip 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? yesDP; 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? yesFL+DP+SecAgg; noFL noise multiplier, SecAgg quorum
Output adversary Is the analyst untrusted? central DP vs local DP per-report ε\varepsilon split
Exactness + throughput Exact result at high QPS? attested HW → TEE; else → MPC enclave attestation, t-of-n
Utility budget Tolerable spatial error? tightens ε\varepsilon, clip norm b=Δf/εb=\Delta f/\varepsilon, 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 b=Δf/εb = \Delta f / \varepsilon. 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.

python
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.

python
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_honest was left at its default False for 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 to True so the router returns FL+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 ε\varepsilon 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 (ε,δ)(\varepsilon, \delta) 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.

Up: Privacy model comparison · Core Fundamentals & Architecture for Spatial Privacy