Self-hosted

Pulse self-hosted

We deliver the entire risk intelligence set onto your machines. You self-host it and you run the queries. The interface is identical to the public API, but every lookup happens inside your own network — we do not even learn which addresses you checked.

The other product is Tide (ingest your traffic, surface the attack in progress) · compare the two

The problem it solves

You already know where in your risk pipeline you want to check an address — login, signup, checkout, withdrawal. The one obstacle is that the address must not leave your network.

Sometimes that is compliance; often it is a more practical concern. Over a public API we can see which addresses you looked up, when, and how often. The queries are themselves data — they reveal your user mix, the rhythm of your risk controls, and what you are currently investigating. Self-hosting cuts that channel too.

A traditional IP database gives you a label; we give you a judgement that expires

The same address was a proxy three days ago — is it still one today? A traditional intelligence database answers “yes”: once labelled, labelled for a long time. Our answer depends on how old the evidence is: the score falls continuously as evidence ages and reaches zero once it expires.

The chart below is illustrative. How fast each class of risk decays, and how long its freshness window is, are part of the scoring definition and are not published; every response carries the definition version, so you can check that results are consistent within one version and ask us to explain the impact when it changes.

The score falls as evidence ages (illustrative) An illustrative chart with no specific values. The horizontal axis is how long ago the evidence was captured; the vertical axis is the score. Our score falls continuously as evidence ages and reaches zero once it expires. For contrast, a traditional static label stays at a constant high value and never changes with time. How fast each class of risk decays, and how long its freshness window is, are part of the scoring definition and are not published here. Static label: marked once, valid indefinitely Our score: falls as evidence ages, zero once expired Score Time since the evidence was captured →

So a score of 0 means “no verifiable evidence”, not “safe”

The distinction matters: treating 0 as “cleared” turns our blind spots into your safe list. What we can judge covers only the share of your traffic for which valid evidence exists — measured on real customer traffic, between 18% and 69% of addresses have a record (the spread depends heavily on traffic mix), and of those, 35%–46% still score above zero right now.

A static label does not have this problem because it never admits it has expired — the price being that a mark made three months ago is still scoring your users highly today. Which is more dangerous depends on whether you fear misses or false positives more. We chose to admit that evidence expires and to put that fact in the response, so you can set your own thresholds.

The queries are themselves data

Over a public API we can see which addresses you looked up, when, and how often. That is not “just metadata” — it directly exposes your user mix, the rhythm of your risk controls, and what you are currently investigating.

Once self-hosted, lookups stay inside your network. Only one connection remains between us, and it runs the other way: we push intelligence to you.

Data flow: public API versus self-hosted Over a public API every lookup reaches us, so we hold a record of which addresses you checked, when, and how often. Self-hosted, lookups stay inside your network and we only push you the full intelligence package, which is the same for every customer and carries no information about which addresses you care about. Public API Your risk system every lookup Our service which leaves us holding: addresses checked · when · how often Self-hosted Your network Your risk system lookup Your instance Our service full intelligence package identical for every customer Lookups never leave your network — we never receive the request, so there is no record to hold

What you get

Not “a private line for querying us”, but the whole intelligence set handed over for you to self-host. Lookups hit your own instance and produce no record on our side.

The full set, on your machines

Not a sample, not fetched on demand. Currently 22.16 million risk profiles, about 3.76 GB, landing whole in your storage and updated incrementally after that.

No lookup record exists on our side

GET /pulse/v1/ip/{ip} hits your own instance. We never receive the request, so there is no record of which addresses you checked, when, or how often.

It can run fully air-gapped

Import over offline media: tide-adm mirror-sync -import. The package is bound to your licence and is only written to the database once the whole package verifies; if it fails midway, rerun with the same package. Your machines never need outbound access.

Same interface as the public Pulse

The response fields match the public ip99.com/pulse/v1/ip/{ip} (score, advice, evidence, scoring moment); a local instance additionally exposes the full evidence fields and the resource-pool handle. If you already call the public Pulse, change the hostname and you are done. If you call the older /v1/ip profile endpoint, the response shape differs — integrate once against the reference shipped with the package. There is also /pulse/v1/replay/{ip}, which scores against a timestamp you supply, for asking “would this have been blocked if we had been running it then?”

Three things we would rather state up front

1. Even when you sync over the internet, we still cannot see what you looked up. The only outbound connection is you pulling the intelligence package, and that package is the full set, identical for every customer, carrying nothing about which addresses you care about. Choose offline media and even that connection disappears.

2. Intelligence expires, and it does so silently. Scores decay with the distance between the evidence and the scoring moment. Measured on the same batch of 192 addresses, four days after the mirror stopped updating they went from all scoring ≥50 to all scoring 0 — the service was entirely healthy and kept answering, only the detection rate had gone to zero. So healthz reports how old the newest evidence is, and the console states it at the top. Alert on that field, not on whether the process is alive.

3. Delivery carries anonymous cluster handles only. You get the full risk profiles, but a resource pool's identity is delivered only as an anonymous handle: you learn that these addresses belong to one pool, not what that pool is called. Handles are derived from your key and cannot be joined across customers.

Deployment

Much simpler than Tide: no traffic ingestion — install it, configure mirror sync, and query.

  1. Install and start the service

    Unpack, fill in one config file (licence name, Redis address), install the systemd unit, check health. Same binary and same deployment guide as Tide.

  2. Import the intelligence mirror

    With internet access: install the sync timer and it updates incrementally from then on.
    Without: import over offline media with tide-adm mirror-sync -import. The package is bound to your licence and is only written once the whole package verifies; if it fails midway, rerun with the same package.

  3. Point your calls at the local instance

    If you already call the public Pulse endpoint, replace ip99.com with your instance and the fields match. If you call /v1/ip, the response shape differs; either way, integrate once against the reference shipped with the package.

  4. Wire mirror freshness into monitoring

    healthz reports how old the newest evidence is, and /metrics exposes the same value. Alert on that field, not on whether the process is alive — when the mirror stops updating the service looks perfectly healthy while the detection rate falls.

Reference specification

The specification follows the size of the intelligence set, not your query volume.

Records22.16 million (measured, full set)
Mirror memory3.76 GB (192 bytes/record); budget 5–6 GB
Throughputabout 850 QPS per core, P99 27 ms
Outbound connectionsOne, for intelligence sync only; zero with offline media

Contact sales · request a quote

Priced separately, and the price depends on deployment size and integration scope, so it is not listed here. Tell us what you need and we will come back with a quote and a deployment plan for your situation.

Describe your needs, get a quote
Delivery format, system requirements and acceptance criteria all ship with the package. If you would like the technical detail first, say so in your enquiry and we will share the deployment guide and the full acceptance criteria when we talk.