Writing Secrets
Programmatically add or update secrets from your application.
The set() method allows your application to add or update secrets programmatically, enabling dynamic configuration, feature flags, and more.
Basic Usage#
await redenv.set("LOG_LEVEL", "debug");This encrypts and writes the new value to Redis, creating a new version entry.
How It Works#
When you call set():
- Encrypts the value locally using the Project Encryption Key (PEK)
- Writes the encrypted value to Redis as a new version
- Clears the local cache to ensure fresh data on next read
Practical Examples#
Feature Flags#
Toggle features in real-time without redeploying:
// Admin endpoint to toggle a feature
app.post("/admin/feature/:name", async (req, res) => {
const { name } = req.params;
const { enabled } = req.body;
await redenv.set(`FEATURE_${name.toUpperCase()}`, String(enabled));
res.json({ success: true, feature: name, enabled });
});// Check the feature flag elsewhere
const secrets = await redenv.load();
const betaEnabled = secrets.get("FEATURE_BETA").toBool();
if (betaEnabled) {
// Show beta features
}Dynamic Log Levels#
Adjust logging without restart:
// Increase verbosity during an incident
await redenv.set("LOG_LEVEL", "debug");
// Return to normal after investigation
await redenv.set("LOG_LEVEL", "info");Rate Limit Adjustments#
Respond to traffic changes:
// During high traffic, increase limits
await redenv.set("RATE_LIMIT_REQUESTS", "1000");
await redenv.set("RATE_LIMIT_WINDOW", "60");
// Normal operations
await redenv.set("RATE_LIMIT_REQUESTS", "100");Maintenance Mode#
async function enableMaintenanceMode(reason: string) {
await redenv.set("MAINTENANCE_MODE", "true");
await redenv.set("MAINTENANCE_REASON", reason);
}
async function disableMaintenanceMode() {
await redenv.set("MAINTENANCE_MODE", "false");
}Auditing#
All writes are audited. The tokenId is recorded with each version:
// Your write operation
await redenv.set("API_KEY", "new-value");
// In the version history (viewable via CLI):
// Version 5: { value: "...", tokenId: "stk_...", timestamp: "..." }Use redenv history view API_KEY to see who changed what and when.
Error Handling#
import { RedenvError } from "@redenv/client";
try {
await redenv.set("KEY", "value");
console.log("Secret updated successfully");
} catch (error) {
if (error instanceof RedenvError) {
console.error("Failed to write secret:", error.message);
}
throw error;
}Cache Behavior#
After a set() call, the local cache is cleared:
// Load current secrets
let secrets = await redenv.load();
console.log(secrets.MY_KEY); // "old-value"
// Update the secret
await redenv.set("MY_KEY", "new-value");
// Next load gets fresh data
secrets = await redenv.load();
console.log(secrets.MY_KEY); // "new-value"Security Considerations#
Best Practices#
- Audit writes - Regularly review version history for unexpected changes
- Validate inputs - Sanitize values before writing
// Example: Validate before writing
async function updateLogLevel(level: string) {
const validLevels = ["debug", "info", "warn", "error"];
if (!validLevels.includes(level)) {
throw new Error(`Invalid log level: ${level}`);
}
await redenv.set("LOG_LEVEL", level);
}Limitations#
- String values only - Convert objects to JSON strings
- No bulk writes - Call
set()for each key - Version history - Each write creates a new version
// Writing JSON
await redenv.set(
"CONFIG",
JSON.stringify({
feature: "enabled",
timeout: 5000,
}),
);
// Reading it back
const config = secrets.get("CONFIG").toJSON();