Which VAPID key goes where?
The public key goes to the browser; the private key stays on your server. Web Crypto creates a matching ECDSA P-256 pair here. The public key is an uncompressed 65-byte point, encoded as 87 base64url characters. The private scalar is 32 bytes, encoded as 43 base64url characters. Neither output includes padding.
VAPID identifies the application server to a push service. It is separate from the encryption keys in each user's PushSubscription. See RFC 8292 and the web-push library.
Generate a pair on your own machine
npx web-push generate-vapid-keys --json
Generate once, store both values and reuse them for that application. Keep the private key in server-side secret storage. Never put it in a client bundle or a public environment variable.
Configure a Node.js push server
const webpush = require('web-push');
webpush.setVapidDetails(
process.env.VAPID_SUBJECT,
process.env.VAPID_PUBLIC_KEY,
process.env.VAPID_PRIVATE_KEY
);
Set VAPID_SUBJECT to a contact URI you control, such as a mailto address. The server library uses the private key to sign VAPID authentication tokens.
Subscribe with the public applicationServerKey
// registration is your active service worker registration.
// Supply only the public key generated above.
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: publicVapidKey
});
Subscription belongs in your application's permission flow. This generator does not register a service worker, request notification permission or send a push message.
Why changing the key pair can break delivery
Subscriptions can be restricted to the public key used when they were created. Keep the corresponding private key available for those subscriptions. A replacement pair does not automatically update clients; plan resubscription and a transition for existing users.
A 256-bit curve does not mean 256-bit attack resistance: P-256 provides roughly 128-bit security. Do not substitute a random hex secret for a valid elliptic-curve key pair.