Bonaventure OgetoBy Bonaventure Ogeto|

Paystack Keys in Vercel, Railway and Render

On Vercel, add PAYSTACK_SECRET_KEY to environment variables in Project Settings and scope it to Production only. Use test keys for Preview and Development. On Railway, add variables in the service Settings tab. On Render, use the Environment section in your service dashboard. All three platforms encrypt variables at rest and inject them at runtime.

Why Platform Setup Matters

Storing Paystack keys correctly on your deployment platform is just as important as keeping them out of your source code. A key that is properly stored in a .env file locally can still be misconfigured on the platform, leading to test keys in production (payments silently fail) or live keys in preview environments (test clicks charge real money).

Each platform has its own variable scoping model, encryption behavior, and gotchas. This guide covers Vercel, Railway, and Render because they are the most commonly used platforms by developers building Paystack integrations in Africa.

For the fundamentals of environment variable management, see storing Paystack keys in environment variables properly.

Vercel: Complete Setup

Vercel is the most popular platform for Next.js deployments, and Next.js is one of the most common frameworks for Paystack integrations. Vercel has a powerful but sometimes confusing environment variable system.

Adding Variables

  1. Go to your project in the Vercel dashboard
  2. Click Settings, then Environment Variables
  3. Add each variable with the correct scope
Variable NameValueEnvironments
PAYSTACK_SECRET_KEYsk_live_xxxxProduction only
PAYSTACK_SECRET_KEYsk_test_xxxxPreview, Development
NEXT_PUBLIC_PAYSTACK_KEYpk_live_xxxxProduction only
NEXT_PUBLIC_PAYSTACK_KEYpk_test_xxxxPreview, Development

You can set the same variable name with different values for different environments. Vercel resolves the correct value based on which environment the deployment targets.

Vercel-Specific Gotchas

  • NEXT_PUBLIC_ prefix. Variables with this prefix are embedded in the client-side JavaScript bundle. Only use this for your public key (pk_*). Never prefix your secret key with NEXT_PUBLIC_.
  • Preview deployments. Every pull request gets a preview deployment. If you scope live keys to "Preview," anyone clicking the preview link processes real payments. Always use test keys for Preview.
  • Build vs runtime. NEXT_PUBLIC_ variables are resolved at build time. Server-side variables are available at runtime. This means you cannot change a NEXT_PUBLIC_ variable and have it take effect without redeploying.
  • Vercel CLI. When using vercel dev locally, Vercel pulls the Development-scoped variables. Make sure Development uses test keys.

Verifying Your Setup

After adding variables, trigger a new deployment and check your server logs. Add a temporary startup log (remove it after verification):

// pages/api/health.js (temporary, remove after verification)
module.exports = function handler(req, res) {
  var keyPrefix = (process.env.PAYSTACK_SECRET_KEY || '').substring(0, 8);
  console.log('Paystack key prefix: ' + keyPrefix);
  res.json({ status: 'ok', keyPrefix: keyPrefix });
};

This logs only the prefix (sk_test_ or sk_live_), not the full key. Verify the prefix matches what you expect for each environment, then remove the endpoint.

Railway: Complete Setup

Railway makes environment variable management straightforward. Variables are set per service and are available at runtime.

Adding Variables

  1. Open your project in the Railway dashboard
  2. Click on the service that runs your Paystack integration
  3. Go to the Variables tab
  4. Click "New Variable" and add each key
PAYSTACK_SECRET_KEY = sk_live_xxxxxxxxxxxxxxxxxxxx
PAYSTACK_PUBLIC_KEY = pk_live_xxxxxxxxxxxxxxxxxxxx

Railway-Specific Features

  • Variable references. Railway lets you reference variables from other services using the ${{service.VARIABLE}} syntax. Useful if multiple services need the same Paystack keys.
  • Shared variables. You can create shared variable groups that apply across services in the same project.
  • Environments. Railway supports multiple environments (production, staging). Create separate environments and set test keys for staging, live keys for production.
  • No build-time embedding. Railway injects all variables at runtime. There is no equivalent of Vercel's NEXT_PUBLIC_ behavior. If you are running a Next.js app on Railway, you need to handle client-side variables differently.

Next.js on Railway

Because Railway does not have build-time variable embedding like Vercel, you need to pass the public key to the client through an API route or a server component:

// pages/api/config.js
module.exports = function handler(req, res) {
  res.json({
    paystackPublicKey: process.env.PAYSTACK_PUBLIC_KEY,
  });
};

Or set the variable as a build argument in your Dockerfile or railway.toml so it is available during the Next.js build step.

Render: Complete Setup

Render provides a clean interface for managing environment variables per service.

Adding Variables

  1. Go to your service in the Render dashboard
  2. Click Environment in the left sidebar
  3. Add each variable under "Environment Variables"
PAYSTACK_SECRET_KEY = sk_live_xxxxxxxxxxxxxxxxxxxx
PAYSTACK_PUBLIC_KEY = pk_live_xxxxxxxxxxxxxxxxxxxx

Render-Specific Features

  • Environment Groups. Render supports environment groups that can be shared across multiple services. Create a "paystack-keys" group and attach it to every service that needs Paystack access.
  • Secret files. For more complex configurations, Render lets you create secret files that are mounted into the container at a specified path. This is useful if you need to store keys in a JSON or YAML config file rather than individual variables.
  • Auto-deploy on change. Render does not automatically redeploy when you change environment variables. You need to trigger a manual deploy or push a new commit for the changes to take effect.
  • Preview environments. Render's preview environments (for pull requests) inherit the service's environment variables by default. Override them for preview environments to use test keys.

Render with Docker

If you deploy with Docker on Render, environment variables are injected at runtime, not during the build. Do not use ARG to pass Paystack keys during the build step, as build arguments can be cached in image layers.

# Dockerfile
# WRONG: build arg cached in image layer
ARG PAYSTACK_SECRET_KEY

# RIGHT: read from environment at runtime
# (just use process.env.PAYSTACK_SECRET_KEY in your code)

Handling Multiple Services

Many Paystack integrations involve multiple services: a web server, a webhook handler, a background worker, and maybe a cron job. Each service that interacts with the Paystack API needs the secret key.

The cleanest approach varies by platform:

  • Vercel: If all services are in the same Vercel project, they share environment variables. If they are separate projects, duplicate the variables or use Vercel's environment variable sharing between projects.
  • Railway: Use shared variable groups. Create a group called "paystack" with the keys, and attach it to every service that needs them.
  • Render: Use environment groups. Same concept as Railway's shared variables.

Regardless of platform, keep the variable names consistent across all services. Use PAYSTACK_SECRET_KEY everywhere, not PAYSTACK_KEY in one service and PS_SECRET in another. Consistency prevents confusion during debugging and key rotation.

Rotating Keys on Each Platform

When you rotate Paystack keys (because of a leak, a team change, or a security policy), you need to update the keys on your deployment platform and redeploy.

Rotation Checklist

  1. Generate new keys on the Paystack dashboard
  2. Update the environment variables on your platform
  3. Trigger a new deployment (or restart the service)
  4. Verify the new keys work by processing a test transaction
  5. Confirm the old keys no longer work

Platform-Specific Notes

  • Vercel: Updating an environment variable automatically triggers a redeployment for Production. Preview deployments use the new value on the next push.
  • Railway: Updating a variable triggers an automatic redeploy of the affected service.
  • Render: You must manually trigger a deploy after updating variables. Changing the variable alone does not redeploy.

The window between rotating the key on Paystack and deploying the new key is a period of downtime. Paystack invalidates the old key immediately upon rotation. Plan your rotation during low-traffic hours to minimize the impact. For zero-downtime strategies, see rotating Paystack secret keys without downtime.

Security Checklist for All Platforms

Before going live with any platform, verify these items:

  • Secret key (sk_live_*) is scoped to Production environment only
  • Preview and staging environments use test keys (sk_test_*)
  • Secret key variable name does not have a client-exposing prefix (NEXT_PUBLIC_, VITE_, REACT_APP_)
  • No environment variables are logged in build output or application logs
  • If using Docker, keys are injected at runtime, not baked into the image
  • Team members who leave the organization have their platform access revoked
  • Environment variable access is restricted to team members who need it (not all team members on the platform)

For the complete security guide, see Paystack security, keys and PCI compliance.

Key Takeaways

  • Vercel scopes environment variables to Production, Preview, and Development. Set live Paystack keys for Production only and test keys for Preview and Development.
  • Railway injects environment variables at runtime. Variables are encrypted at rest and not visible in build logs unless you explicitly log them.
  • Render provides an Environment section in each service dashboard. Variables are encrypted and available at runtime to web services and background workers.
  • Never use the NEXT_PUBLIC_ prefix for Paystack secret keys on Vercel. This embeds them in the client-side JavaScript bundle.
  • Preview deployments on Vercel should always use test keys. A reviewer clicking a preview link should not trigger real payments.
  • All three platforms support referencing shared environment groups, which is useful when multiple services need the same Paystack keys.

Frequently Asked Questions

Can I use the same Paystack keys across Vercel, Railway, and Render?
Yes, the same keys work on any platform. The platform only stores and injects the variable. The key itself is tied to your Paystack account, not to a specific hosting provider.
What happens if I forget to set the environment variable on the platform?
Your application will read undefined for the variable. If your code does not validate at startup, the first Paystack API call will fail with a 401 Unauthorized error. Add startup validation to catch this immediately.
Should I encrypt my Paystack keys before storing them on the platform?
No. All three platforms (Vercel, Railway, Render) encrypt environment variables at rest. Adding your own encryption layer adds complexity without meaningful security benefit.
How do I handle Paystack webhook secrets on these platforms?
Store the webhook secret (your Paystack secret key, used for HMAC signature verification) as a separate environment variable like PAYSTACK_WEBHOOK_SECRET. In practice, this is the same value as PAYSTACK_SECRET_KEY, but keeping it as a separate variable makes your code more readable.
Can platform support staff see my environment variables?
Platform policies vary. Generally, environment variables are encrypted and not visible to support staff. However, if your code logs the variable values to a logging service, anyone with access to those logs can see them. Never log secret key values.

Ready to build real-world apps?

Join the McTaba Labs full-stack marathon (4 months full-time · 6 months part-time). Learn M-Pesa, USSD, and WhatsApp engineering while shipping 8 production apps.

Apply to the McTaba Marathon