⚡ ⚡ Learn how Investing.com uses Jitsu to move data faster

Data residency for fintech: self-hosted Jitsu in your own network

For a bank or lender whose policy keeps customer data in its own network, data residency means the event pipeline runs there too. Self-hosted Jitsu gives a regulated team exactly that: the pipeline runs in your network under the MIT license, and events go only to the destinations you configure. Jitsu is open source, and you deploy it on Kubernetes with the Jitsu operator, following the production deployment guide: ingest, rotor, bulker, the console, the operator and the function servers it manages, with PostgreSQL, Kafka or Redpanda, ClickHouse and MongoDB underneath.

This page is for the platform or infrastructure lead, security architect or data platform lead at a bank, lender or payments company. It is part of the fintech hub.

TL;DR

  • Self-hosted Jitsu runs in your network, free under the MIT license, with no usage limits.
  • Events go only to the destinations you configure.
  • A production install runs on Kubernetes with the Jitsu operator, which routes every event, following the production deployment guide.
  • Self-hosted Jitsu does not archive events, so a raw copy belongs in a warehouse or file-storage destination you run.
  • Identity stitching has no plan restriction on a self-hosted install.

The problem in plain words

A regulated team reviewing any event pipeline asks three things: where it runs, what leaves the network, and what the vendor can sign. When policy keeps customer data in the company network, a SaaS pipeline fails the first question. In-house code passes it, at the price of a new consumer for every new feed.

Self-hosting an open-source pipeline sits between the two, and the operating work moves to your platform team. This page lists that work; the self-hosted vs managed comparison covers what it costs to run.

What a self-hosted install needs

ComponentWhat it doesNeeded
Kubernetes clusterRuns every serviceAlways: the operator, which routes every event, runs on it
Jitsu operatorProvisions function servers and keeps their routing tableFor routing any event, even with no custom functions
PostgreSQLConfiguration and metadataAlways
Kafka or RedpandaTransport between servicesAlways
ClickHouseJitsu's own events log and metricsAlways
MongoDBFunction key-value store and identity stitchingFor those features
RedisAlternative functions state storeOptional
SyncctlConnector syncs as Kubernetes CronJobsOnly with connectors

The list comes from the production deployment guide, which also covers the Kubernetes permissions the operator needs. Docker Compose, the legacy setup, is deprecated and cannot run functions or connector syncs (self-hosting overview). To try every service locally first, the quick start deploys them to Minikube.

Identity stitching, an Enterprise feature on Jitsu Cloud, has no plan restriction on a self-hosted install. It needs MongoDB, rewrites anonymous events in six warehouses (ClickHouse, BigQuery, PostgreSQL, Redshift, Snowflake, MySQL), and goes back up to 30 days.

The events

EventSent fromRequired propertiesIn events_rawIn events (masked)
identifyBrowser, app, backenduserId, trait emailtraits as sentemail hashed with SHA-256; phone, name, first_name, last_name, address removed
pageBrowserurlIP address as sentIPv4 address with the last octet set to 0 in context.ip and requestIp; IPv6 removed
Account CreatedBackendsignup_methodas senttraits masked as above
KYC RejectedBackendkyc_provider, reason_categoryas senttraits masked as above
Deposit CompletedBackenddeposit_id, amount, currency, funding_methodas sentamounts unchanged

Events reach a self-hosted install the same way they reach Jitsu Cloud, at your own domain: the HTTP API with a server-to-server write key and Strict Mode, Jitsu's JavaScript library on the web. The full list of 35 events, with PII handling for each, is in the fintech tracking plan (CSV), and the backend calls are written out on the onboarding and KYC funnel page.

The function: a raw copy and a masked copy

Inside your own network, one split keeps an unmodified copy for reconciliation and investigations, readable by a few people, and a masked copy for analysts. Monzo's data stack write-up describes the same split, sanitized and raw event tables in BigQuery, built in-house. In Jitsu it is one function on the warehouse connection; paste it into the function editor in the console, which allows the crypto import:

import { hash } from "crypto";

const RAW_TABLE = "events_raw";
const TEST_USERS = new Set(["integration-tests"]);
const HASHED_TRAITS = ["email"];
const REMOVED_TRAITS = ["phone", "name", "first_name", "last_name", "address"];

function maskTraits(traits) {
  if (!traits || typeof traits !== "object") return undefined;
  const out = { ...traits };
  for (const key of REMOVED_TRAITS) delete out[key];
  for (const key of HASHED_TRAITS) {
    if (typeof out[key] === "string") out[key] = hash("sha256", out[key].trim().toLowerCase());
  }
  return out;
}

// 203.0.113.42 becomes 203.0.113.0. Anything that is not an IPv4 address is removed.
function truncateIp(ip) {
  return typeof ip === "string" && /^\d{1,3}(\.\d{1,3}){3}$/.test(ip) ? ip.replace(/\.\d{1,3}$/, ".0") : undefined;
}

// Must be the last function on the connection: it returns two events.
export default async function rawAndMaskedCopy(event) {
  if (TEST_USERS.has(String(event.userId))) return "drop";

  const context = event.context ?? {};
  const masked = {
    ...event,
    requestIp: truncateIp(event.requestIp),
    context: { ...context, ip: truncateIp(context.ip), traits: maskTraits(context.traits) },
  };
  if (event.traits) masked.traits = maskTraits(event.traits);

  return [{ ...event, JITSU_TABLE_NAME: RAW_TABLE }, masked];
}
  • It returns two events, so it has to be the last function on the connection: only the last function may return more than one event (advanced functions).
  • Jitsu records the sender's IP address in requestIp on every event, separately from context.ip, so the masked copy truncates both.
  • Run the PII guardrail from the fintech hub before it, so card numbers reach neither copy.
  • An unsalted SHA-256 of an email is pseudonymous, not anonymous: anyone holding a list of emails can match it. Treat the masked table as personal data, and restrict events_raw to the people who need plaintext.
  • Splitting doubles the event count. On Jitsu Cloud each resulting event is billed as an active event; a self-hosted install under the MIT license has no Jitsu bill.

Querying it

ClickHouse, against the two tables the function writes. FINAL collapses rows that share a message_id, so retries do not inflate either count, and the timestamp filters keep it to the last 30 days.

-- ClickHouse. Daily row counts in the raw and masked copies, and any plaintext email or full IPv4 address left in the masked one.
SELECT
    day,
    raw_rows,
    masked_rows,
    raw_rows - masked_rows AS difference,
    plaintext_emails,
    full_ips
FROM
(
    SELECT toDate(timestamp) AS day, count() AS raw_rows
    FROM events_raw FINAL
    WHERE timestamp >= today() - 30
    GROUP BY day
) AS raw
FULL OUTER JOIN
(
    SELECT
        toDate(timestamp) AS day,
        count() AS masked_rows,
        countIf(position(context_traits_email, '@') > 0) AS plaintext_emails,
        countIf(match(request_ip, '^\\d+\\.\\d+\\.\\d+\\.\\d+$') AND NOT endsWith(request_ip, '.0')) AS full_ips
    FROM events FINAL
    WHERE timestamp >= today() - 30
    GROUP BY day
) AS masked USING (day)
ORDER BY day;

A non-zero difference means one copy failed to load on that day; check bulker's results in Live Events.

If plaintext_emails is above zero, events reached events without passing the function, for example from a connection that does not run it. An email sent as a property lands in its own column, such as email, which this check does not read.

Private Cloud and On Prem

On Prem and Private Cloud are on the Enterprise plan (pricing, contact sales). Jitsu Cloud itself is hosted in the United States.

Example implementation (illustrative): a consumer lender running its own cluster

Illustrative example: not a Jitsu customer.

A consumer lender keeps customer data inside its own cloud account and already runs Kubernetes there. Its platform team deploys Jitsu on Kubernetes with the Jitsu operator, following the production deployment guide. The web app uses Jitsu's JavaScript library and the loan system posts application and decision events over the HTTP API.

One connection writes to its warehouse with the guardrail first and the raw-and-masked function last. Analysts read events, a short access list covers events_raw, and the reconciliation query runs daily.

Where Jitsu does not fit

  • Kubernetes is required to route any event, and for functions and connector syncs. Docker Compose is deprecated and cannot run them.
  • Profile Builder is documented on the Enterprise plan of Jitsu Cloud only (profiles docs).
  • Event backups are a Jitsu Cloud feature; self-hosted Jitsu does not archive events (event backups). Keep a raw copy in a destination you run.
  • Functions are JavaScript, or TypeScript built with the Jitsu CLI, and there is no Python runtime.

Questions people ask

Is self-hosted Jitsu free? Yes. Jitsu is open source under the MIT license, with no usage limits on a self-hosted install. On Prem and Private Cloud are on the Enterprise plan.

Where does event data go on a self-hosted install? To the destinations you configure, inside or outside your network.

How is a production install deployed? On Kubernetes with the Jitsu operator, following the production deployment guide.

Can Jitsu Cloud keep data in a specific region? Jitsu Cloud is hosted in the United States and no other Cloud region is documented. For data that has to stay in a region, self-host Jitsu. On Prem and Private Cloud are on the Enterprise plan.

Get started with Jitsu

On Prem and Private Cloud are on the Enterprise plan (Book a demo). To try the pipeline on your own events first, Get started on Jitsu Cloud, or follow the self-hosting quick start.

Subscribe to the Jitsu newsletter
Occasional product updates when we ship something worth knowing about. No spam.