/No code changes

Get started

No code changes

Send every SDK through Vallkey with one environment variable, in Node.js, Bun, Python, Ruby, Java, .NET, PHP and Elixir.

Most SDKs can be pointed at Vallkey with their own address setting. With no-code mode you skip even that: a small hook, loaded by one environment variable when your app starts, sends every request that carries a ghost key to Vallkey, with the same path. Requests without a ghost key are not touched, and your code stays exactly as the SDK's docs show it, with the ghost key as the key.

Run this in your project folder. It tells the language from your files, downloads the hook file where the language needs one, checks it, and prints what to set:

Terminal
npx vallkey hook          # or name it: npx vallkey hook java
LanguageThe one settingCovers
Node.jsNODE_OPTIONS='--require vallkey/auto'fetch, http and https: almost every JavaScript SDK
BunBUN_OPTIONS='--preload vallkey/auto'the same
PythonVALLKEY_AUTO=1httpx, requests, urllib3, boto3, aiohttp, urllib
RubyRUBYOPT=-rvallkey/autoNet::HTTP, and Faraday, HTTParty and rest-client on top of it
Java, Kotlin, ScalaJAVA_TOOL_OPTIONS=-javaagent:/opt/vallkey/vallkey-agent.jarOkHttp, Apache HttpClient 4 and 5, the JDK HttpClient, HttpURLConnection
.NETDOTNET_STARTUP_HOOKS=/opt/vallkey/Vallkey.Auto.dllHttpClient
PHPPHP_INI_SCAN_DIR=:/opt/vallkey/phpthe curl extension: Guzzle, Symfony HttpClient and the SDKs' own clients
Elixir, ErlangELIXIR_ERL_OPTIONSFinch (Req), hackney (HTTPoison), httpc (Tesla's default)

Set it wherever your app's environment lives: your hosting dashboard, your Dockerfile, or the shell that starts the app. Then restart the app.VALLKEY_DEBUG=1 logs each request sent to Vallkey (never the key), and VALLKEY_AUTO=0 turns it off.

Where it's used

Each key's Activity tab lists every place it is used from, live: the platform, the language and the name you gave it, today's requests, and anything wrong there, such as requests the rules blocked or that the provider refused, with what to do about it. The hooks tell Vallkey the platform themselves (Vercel, AWS Lambda, Cloud Run, Azure, Railway, Render, Fly.io, Heroku, Kubernetes, Docker and more); for other requests it is the SDK and the network they came from. Name each place with VALLKEY_ENV:

Environment
VALLKEY_ENV=production   # or staging, eu-workers…

npx vallkey status shows the same from the terminal, and exits with 1 when a place is failing, so a deploy script can stop on it. A place that sent steady traffic and then nothing for two hours sends an alert, through your alert routing. For separate rules and a separate kill switch per place, give each place a ghost key of its own: Add another place on the key makes one for the same real key.

Node.js and Next.js

Terminal
npm install vallkeyNODE_OPTIONS='--require vallkey/auto' npm start

On Next.js, npx vallkey hook adds an instrumentation.ts instead, which Next.js runs when it starts, on your servers and on Vercel, where an environment variable cannot load a package the build did not include. In any app you can also put import 'vallkey/auto' first, before any SDK.

Docker

For the languages whose hook is a file, npx vallkey hook prints lines for your Dockerfile that download it and check its checksum. For example, Java:

Dockerfile
# syntax=docker/dockerfile:1FROM eclipse-temurin:21-jreADD --checksum=sha256:<from npx vallkey hook> https://vallkey.com/downloads/hooks/0.1.0/vallkey-agent-0.1.0.jar /opt/vallkey/vallkey-agent.jarENV JAVA_TOOL_OPTIONS="-javaagent:/opt/vallkey/vallkey-agent.jar"

The files are listed with their checksums in SHA256SUMS. PHP has a build for each PHP from 8.2 to 8.5, thread-safe or not (FrankenPHP is thread-safe), for glibc and Alpine, on x86-64 and ARM; the command picks the one your Dockerfile's PHP needs.

Elixir

Terminal
export ELIXIR_ERL_OPTIONS='-eval catch(code:load_abs("/opt/vallkey/vallkey_auto")),catch(vallkey_auto:start()).'mix phx.server     # or: bin/my_app start

It is loaded by its path because releases load nothing on demand, and wrapped in catch so a missing file never stops your app. A release starts it when its boot finishes, so requests made while your applications are still starting go out as they are. Plain Erlang releases use ERL_FLAGS.

What it does not cover

  • Go, Rust and other compiled languages: nothing is left to change once the app is built. Set each SDK's address in its options instead.
  • Edge runtimes (Cloudflare Workers, Vercel Edge functions): there is no setting to load anything first. Add import 'vallkey/auto' at the top of your entry file.
  • .NET apps published as native AOT or trimmed cannot load startup hooks, nor can apps that set DOTNET_SYSTEM_NET_HTTP_ENABLEACTIVITYPROPAGATION=false.
  • PHP's own stream wrappers (file_get_contents on a URL): every common PHP HTTP client uses curl, which is covered.

Note

Tested with each language's official SDKs, used exactly as their docs show, in containers cut off from the internet, so a request the hook missed fails instead of reaching the provider: OpenAI, Anthropic, Gemini, Stripe (with file uploads), Twilio, AWS S3, SendGrid, Resend, GitHub, Slack and more, on Java 11, 17 and 21, .NET 8 and 10, and Elixir with mix and as a release.

Still have a question?

We read every email, usually within a day.

Contact support