McTaba Labs logo
Software EngineeringThe WhiteboardProjectsEventsMasterclassesWebinarsLearn
Book Call

500+ developers already in the community

Get answers, find accountability partners, and stay ahead

Join Discord →
McTaba Labs logo

Educating 1 million students in tech by 2030.

Programs

  • HighSchool Graduates Launchpad
  • AI & Business Automation
  • Corporate Training
  • McTaba Story & Mission
  • Full-Stack Curriculum
  • Course Pricing & Plans
  • Frequently Asked Questions

Resources

  • Join Discord Community
  • Tech Events in Nairobi
  • Masterclasses
  • Free Resources
  • Learn
  • Campus
  • Africa Tech Talent Report
  • Partner With Us
  • Start a Project
  • Our Work

Contact Us

  • 124 Manyani East Road, Lavington, Nairobi
  • +254727795603
  • Book a Discovery Call

Office Hours:

Mon-Fri: 9am - 2pm EAT

Sat: 10am - 12pm EAT

© 2027 McTaba Labs - A product of Edtech Industries. All rights reserved.

Privacy PolicyTerms of ServiceRefund Policy
  1. Learn
  2. Paystack for African Developers
  3. Storing Paystack Keys in Environment Variables Properly
Bonaventure OgetoBy Bonaventure Ogeto|Updated July 22, 2026

Storing Paystack Keys in Environment Variables Properly

Store your Paystack secret key in a server-side environment variable like PAYSTACK_SECRET_KEY. Store the public key in a client-safe variable like NEXT_PUBLIC_PAYSTACK_KEY. Never commit .env files to version control. Use .env.example with placeholder values for documentation, and always verify that your build tool does not bundle secret variables into client-side JavaScript.

In this article

  1. 1. Why Environment Variables Matter for Payment Keys
  2. 2. The .env File and How to Use It
  3. 3. Public vs Secret: Which Variable Goes Where
  4. 4. Framework-Specific Patterns
  5. 5. Validate Keys at Startup
  6. 6. Managing Keys Across Multiple Environments
  7. 7. Common Mistakes to Avoid
  8. 8. When to Use a Secrets Manager

Why Environment Variables Matter for Payment Keys

Hardcoding an API key in a source file is the fastest way to leak it. Once that file is pushed to a repository, the key lives in the commit history forever. Even if you delete the line and push again, anyone with access to the repo can find it in the git log.

Environment variables solve this by separating configuration from code. The key lives on the server (or in a platform's settings panel), not in any file that gets committed. Your code reads the value at runtime. If the key needs to change, you update the variable without touching the codebase.

For Paystack specifically, you are dealing with keys that can authorize real money transfers. A leaked sk_live_ key means an attacker can verify transactions, initiate transfers out of your account, and read all your customer data. The stakes are high enough that getting environment variable management right is not optional.

The .env File and How to Use It

Most Node.js projects use a .env file at the project root, loaded by the dotenv package. Here is what a properly structured .env file looks like for a Paystack integration:

# .env (never commit this file)
PAYSTACK_SECRET_KEY=sk_test_xxxxxxxxxxxxxxxxxxxx
PAYSTACK_PUBLIC_KEY=pk_test_xxxxxxxxxxxxxxxxxxxx
PAYSTACK_WEBHOOK_SECRET=whsk_xxxxxxxxxxxxxxxxxxxx

And the companion file that does get committed:

# .env.example (commit this)
PAYSTACK_SECRET_KEY=sk_test_your_key_here
PAYSTACK_PUBLIC_KEY=pk_test_your_key_here
PAYSTACK_WEBHOOK_SECRET=whsk_your_webhook_secret_here

Load the variables at the start of your application:

// server.js
require('dotenv').config();

// Validate immediately
if (!process.env.PAYSTACK_SECRET_KEY) {
  console.error('PAYSTACK_SECRET_KEY is not set. Exiting.');
  process.exit(1);
}

// Now use it
var secretKey = process.env.PAYSTACK_SECRET_KEY;

The critical step most developers skip: add .env to your .gitignore before your very first commit. If you add it later, the file is already in the history.

# .gitignore
.env
.env.local
.env.production

Get weekly developer tips

Join 25,000+ developers. Practical guides, job tips, and new content — straight to your inbox.

No spam. Unsubscribe anytime.

Public vs Secret: Which Variable Goes Where

Paystack gives you two types of keys, and they have very different security profiles:

Key TypeVariable NameWhere It LivesRisk If Exposed
Public Key (pk_*)PAYSTACK_PUBLIC_KEYFrontend OKLow. Can only open checkout popup.
Secret Key (sk_*)PAYSTACK_SECRET_KEYServer onlyCritical. Full API access.

The public key is designed to be visible in the browser. It is embedded in your JavaScript bundle and appears in the network tab of anyone visiting your site. This is expected. The key can only initialize a checkout. It cannot verify transactions, issue refunds, or move money.

The secret key is the opposite. If it appears anywhere a user can see it (browser console, frontend bundle, public repo, error log), you have a security incident. Treat it like a database password.

A common mistake: storing both keys in the same environment variable pattern and accidentally exposing the secret key through a frontend build tool. The next sections cover how each framework handles this differently.

Framework-Specific Patterns

Every framework has its own rules about which environment variables make it into the browser bundle. Getting this wrong is one of the most common security mistakes in Paystack integrations.

Next.js

Next.js only exposes variables prefixed with NEXT_PUBLIC_ to the browser. Server-side variables stay on the server.

# .env.local
PAYSTACK_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxxxxxx
NEXT_PUBLIC_PAYSTACK_KEY=pk_live_xxxxxxxxxxxxxxxxxxxx

In your frontend component, use process.env.NEXT_PUBLIC_PAYSTACK_KEY. In your API route, use process.env.PAYSTACK_SECRET_KEY. If you accidentally name the secret key NEXT_PUBLIC_PAYSTACK_SECRET_KEY, it will be bundled into your frontend JavaScript. Do not do this.

Vite (React, Vue, Svelte)

Vite exposes variables prefixed with VITE_ to the browser.

# .env
PAYSTACK_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxxxxxx
VITE_PAYSTACK_KEY=pk_live_xxxxxxxxxxxxxxxxxxxx

Access the public key with import.meta.env.VITE_PAYSTACK_KEY. The secret key without the VITE_ prefix stays out of the bundle.

Express.js / Plain Node.js

Express has no special variable prefix rules. Everything in process.env is server-side. Just make sure you never send environment variables to the client in an API response.

// WRONG: leaks the secret key to the client
app.get('/config', function(req, res) {
  res.json({ key: process.env.PAYSTACK_SECRET_KEY });
});

// RIGHT: only send the public key
app.get('/config', function(req, res) {
  res.json({ key: process.env.PAYSTACK_PUBLIC_KEY });
});

Django / Python

Use python-decouple or django-environ to load from a .env file:

# settings.py
from decouple import config

PAYSTACK_SECRET_KEY = config('PAYSTACK_SECRET_KEY')
PAYSTACK_PUBLIC_KEY = config('PAYSTACK_PUBLIC_KEY')

Laravel / PHP

Laravel reads from .env automatically. Access keys with the env() helper:

// config/services.php
'paystack' => [
    'secret' => env('PAYSTACK_SECRET_KEY'),
    'public' => env('PAYSTACK_PUBLIC_KEY'),
],

Validate Keys at Startup

A missing environment variable should not cause a silent failure on the first payment attempt ten minutes after deployment. It should crash the server immediately at startup, with a clear error message.

// config.js
var requiredVars = [
  'PAYSTACK_SECRET_KEY',
  'PAYSTACK_PUBLIC_KEY',
];

var missing = requiredVars.filter(function(name) {
  return !process.env[name];
});

if (missing.length > 0) {
  console.error('Missing required environment variables: ' + missing.join(', '));
  process.exit(1);
}

// Optional: validate key format
var secretKey = process.env.PAYSTACK_SECRET_KEY;
if (!secretKey.startsWith('sk_test_') && !secretKey.startsWith('sk_live_')) {
  console.error('PAYSTACK_SECRET_KEY does not look like a valid Paystack secret key');
  process.exit(1);
}

module.exports = {
  paystackSecretKey: secretKey,
  paystackPublicKey: process.env.PAYSTACK_PUBLIC_KEY,
};

This pattern catches three common problems: forgetting to set a variable after deployment, copy-pasting the wrong key type, and accidentally setting a public key where a secret key should be.

Managing Keys Across Multiple Environments

Most projects have at least three environments: development (local machine), staging (preview deployment), and production (live). Each should use different Paystack keys.

EnvironmentKey TypePurpose
Developmentsk_test_* / pk_test_*Local coding and debugging
Stagingsk_test_* / pk_test_*Pre-production verification
Productionsk_live_* / pk_live_*Real payments

Use separate .env files for each environment:

.env.development    # local dev, test keys
.env.staging        # staging server, test keys (different account)
.env.production     # production server, live keys

Some teams use the same Paystack test account for development and staging. This works but creates noise. When two developers and the staging server all share test keys, the test dashboard fills with transactions from three sources. Consider creating a separate Paystack business for staging. See staging environments and separate Paystack accounts for details.

Common Mistakes to Avoid

These mistakes show up repeatedly in code reviews and incident reports:

  1. Committing .env before adding .gitignore. If .env is in even one commit, it is in the history forever. Always add .gitignore first.
  2. Using NEXT_PUBLIC_ prefix for the secret key. This bundles the secret key into your frontend JavaScript. Anyone can extract it from the browser.
  3. Logging process.env at startup for debugging. This dumps all environment variables, including secret keys, to your log service. Log individual non-sensitive variables if you must.
  4. Copying keys between environments manually. Use your hosting platform's environment variable UI or a secrets manager. Manual copying leads to live keys in staging or test keys in production.
  5. Storing keys in a config.json file that gets committed. JSON config files are not environment variables. They get committed to version control. Use .env instead.
  6. Not using different keys for staging and production. If staging accidentally uses live keys, a test purchase moves real money.

For a deeper look at what happens when keys do leak and the remediation steps, see what to do if your Paystack secret key leaked.

When to Use a Secrets Manager

Environment variables loaded from .env files work for most projects. But as your team grows, you may want a secrets manager that provides audit logs, automatic rotation, and access control.

Options that work well in the African developer ecosystem:

  • Vercel Environment Variables. Set them in the Vercel dashboard. They are encrypted at rest and injected at build time or runtime depending on the prefix.
  • Railway Variables. Similar to Vercel. Set in the Railway dashboard, encrypted at rest, available at runtime.
  • AWS Secrets Manager. Enterprise-grade. Supports automatic rotation, fine-grained IAM access control, and cross-region replication.
  • HashiCorp Vault. Self-hosted option. Good for teams that need on-premise secrets management or run across multiple cloud providers.
  • Doppler. Developer-friendly SaaS secrets manager. Syncs secrets across environments and integrates with most deployment platforms.

For most Paystack integrations built by small to medium teams in Africa, the hosting platform's built-in environment variable management (Vercel, Railway, Render) is sufficient. Move to a dedicated secrets manager when you need audit trails, programmatic rotation, or multi-service secret sharing.

For platform-specific setup instructions, see Paystack keys in Vercel, Railway and Render.

Key Takeaways

  • ✓Environment variables keep Paystack keys out of source code and version control, reducing the risk of accidental leaks.
  • ✓The secret key (sk_live_* or sk_test_*) belongs in a server-only variable like PAYSTACK_SECRET_KEY. It must never appear in frontend bundles.
  • ✓The public key (pk_live_* or pk_test_*) can go in a client-safe variable like NEXT_PUBLIC_PAYSTACK_KEY or VITE_PAYSTACK_KEY, because public keys can only initialize checkouts.
  • ✓Always add .env to your .gitignore before your first commit. Create a .env.example file with placeholder values so teammates know which variables to set.
  • ✓Validate that required environment variables exist at startup. A missing PAYSTACK_SECRET_KEY should crash the server immediately, not fail silently on the first payment.
  • ✓Different frameworks have different rules for which environment variables reach the browser. Next.js requires NEXT_PUBLIC_ prefix, Vite requires VITE_ prefix. Know your framework.

Frequently Asked Questions

Can I store Paystack keys in a database instead of environment variables?
You can, but it adds complexity without clear benefit for most projects. You need to secure the database connection string (which itself is an environment variable), handle encryption at rest, and ensure the key is not logged in database query logs. Environment variables are simpler and more standard.
What happens if I accidentally use live keys in my test environment?
Any transaction you initialize will process real money. A test purchase with a real card will charge the customer. Always validate the key prefix at startup to catch this mistake before it costs money.
Should I use the same PAYSTACK_SECRET_KEY variable name across all environments?
Yes. Use the same variable name and swap the value. Your code reads PAYSTACK_SECRET_KEY regardless of the environment. The development .env file contains a test key. The production platform contains the live key. The code does not change.
Is it safe to put the public key in my .env file?
Yes. The public key is designed to be visible in the browser. Putting it in .env just keeps your code clean and makes it easy to swap between test and live keys. The key itself is not a secret.
How do I share environment variables with my team?
Never share .env files through chat, email, or version control. Use your hosting platform environment variable settings, a secrets manager like Doppler, or a password manager with shared vaults. Create a .env.example file with placeholder values so teammates know which variables to set.

Learn Paystack Integration

KES 2,999

The definitive guide to building payment systems with Paystack — from your first transaction to production-grade payment infrastructure across Africa. 9 modules, 47 lessons. Free preview available.

Start Paystack Course

Not ready? Create Free Account

Keep reading

Paystack Security, Keys and PCI Compliance: Complete Guide

A complete security reference for Paystack integrations. Covers API key types and rotation, secure key storage, PCI DSS compliance scope, price tampering prevention, webhook replay attacks, rate limiting, fraud signals, and logging without exposing secrets.

Read more

What to Do If Your Paystack Secret Key Leaked

A leaked Paystack secret key is a financial security incident. An attacker with your sk_live_ key can verify transactions, initiate transfers, read customer data, and issue refunds. This guide walks you through the emergency response: immediate rotation, damage assessment, unauthorized activity detection, and prevention measures.

Read more

Replay Attacks on Paystack Webhooks

A replay attack captures a legitimate Paystack webhook and sends it to your server again. The signature is valid because the payload is unchanged. Without idempotency checks, your server processes the same payment twice, granting double value to the attacker. This guide shows how to defend against replays.

Read more

Logging Payments Without Logging Secrets

Good payment logging helps you debug failed charges and reconcile transactions. Bad payment logging leaks your Paystack secret key, card tokens, or customer data into log files that attackers can read. This guide draws a clear line between safe and dangerous payment log data.

Read more

Paystack Dispute Deadline Missed: What Happens

When you miss a Paystack dispute deadline, the money is automatically returned to the cardholder. This decision is final and cannot be reversed. This guide covers what happens, why it happens, and how to build alerts so it never happens to you.

Read more

Explore related topics

M-Pesa & African Stack

M-Pesa Daraja API tutorials, USSD development, and WhatsApp Business API guides. The African Stack that global bootcamps do not teach.

Learn to Code in Kenya

Everything a Kenyan needs to know before writing their first line of code. Career paths, real costs, hardware requirements, and honest answers about what it takes.

Learning to Code

Roadmaps, language guides, and practical advice for learning to code and launching a programming career.

Breaking Into Tech

Practical, no-nonsense guides for anyone looking to start or change their career in tech. From choosing your first language to acing interviews.

The African Stack: Skills for This Market

The skills that make Kenyan developers hard to replace: M-Pesa, USSD, WhatsApp, fintech, and building for the African market.

Bonaventure Ogeto

Bonaventure Ogeto

Founder, McTaba Labs

Bonaventure is the founder of McTaba Labs, a coding bootcamp in Nairobi, Kenya. He has spent years building products for the African market and mentoring the next generation of developers across the continent.