You push your Go Fiber API, it deploys cleanly, health checks pass, and then it crashes on the first request because DATABASE_URL is empty. The deploy screen never asked for it, and now you are SSH-less, staring at a red status indicator, wondering where to inject environment variables after the fact.
The fix is a pandastack.json file in your repo root. Its env array makes the deploy screen prompt for variables instead of silently accepting blank configuration. This is the same workflow that made Vercel deployable with a single click — and PandaStack implements it identically.
Why environment variables fail silently
Go applications often read environment variables with os.Getenv("DATABASE_URL"), which returns an empty string if the variable is not set. Fiber does not crash on startup when a database connection string is missing — it crashes when the first handler tries to query. By then, the deployment is marked successful and your rollback window has passed.
The second problem is the workflow. You create a project, paste a repo URL, and click Deploy. The platform detects Go, runs go build, and starts the binary. If you forgot to configure environment variables beforehand, the app boots with missing configuration. The logs show a connection error five minutes after deploy, and you are left editing variables in the dashboard and manually redeploying.
pandastack.json solves both. Its env array tells the deploy screen "stop and ask for these values before building." If the user leaves a field blank, they see a validation error before the build starts, not after the app has already failed in production.
Create a Fiber API that depends on environment variables
Start with a minimal Fiber application that connects to PostgreSQL. This example uses pgx as the driver and expects three variables: DATABASE_URL, PORT, and JWT_SECRET.
// main.go
package main
import (
"context"
"fmt"
"log"
"os"
"github.com/gofiber/fiber/v2"
"github.com/jackc/pgx/v5/pgxpool"
)
func main() {
dbURL := os.Getenv("DATABASE_URL")
if dbURL == "" {
log.Fatal("DATABASE_URL is required")
}
port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
jwtSecret := os.Getenv("JWT_SECRET")
if jwtSecret == "" {
log.Fatal("JWT_SECRET is required")
}
pool, err := pgxpool.New(context.Background(), dbURL)
if err != nil {
log.Fatalf("Unable to connect to database: %v\n", err)
}
defer pool.Close()
app := fiber.New()
app.Get("/health", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"status": "ok"})
})
app.Get("/users", func(c *fiber.Ctx) error {
var count int
err := pool.QueryRow(context.Background(), "SELECT COUNT(*) FROM users").Scan(&count)
if err != nil {
return c.Status(500).JSON(fiber.Map{"error": err.Error()})
}
return c.JSON(fiber.Map{"user_count": count})
})
log.Fatal(app.Listen("0.0.0.0:" + port))
}The application binds to 0.0.0.0, not localhost. This is critical — containers route external traffic through 0.0.0.0, and an app listening on 127.0.0.1 will pass health checks but reject real requests.
Push this to a GitHub repository. The build will succeed, but deployment will fail if DATABASE_URL or JWT_SECRET are missing.
Add a pandastack.json configuration file
Create pandastack.json in the repo root. This file tells PandaStack how to build and run the app, and which environment variables to prompt for during deployment.
{
"type": "container",
"name": "fiber-api",
"language": "go",
"buildCommand": "go build -o main .",
"startCommand": "./main",
"healthCheckPath": "/health",
"env": [
{
"name": "DATABASE_URL",
"description": "PostgreSQL connection string (postgres://user:pass@host:5432/dbname)"
},
{
"name": "JWT_SECRET",
"description": "Secret key for signing JWT tokens (generate with openssl rand -hex 32)"
},
{
"name": "PORT",
"value": "8080",
"description": "Port the app listens on (defaults to 8080)"
}
]
}The env array accepts two formats: a plain string ("PORT") or an object with name, description, and optional value. If value is omitted, the deploy screen shows an empty text field with the description as a placeholder. The user must fill it before the build starts.
PORT has a default value, so the field is pre-filled but editable. DATABASE_URL and JWT_SECRET are required and will block deployment if left blank.
Commit this file and push to GitHub.
Deploy with the CLI
Install the PandaStack CLI and authenticate:
panda loginThis opens a browser to authenticate and stores a session token locally.
Create the project from the repository:
panda projects create \
--repo github.com/yourusername/fiber-api \
--branch main \
--auto-deployThe CLI detects pandastack.json and prompts interactively for environment variables:
DATABASE_URL: postgres://user:pass@db.pandastack.io:5432/mydb
JWT_SECRET: a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
PORT [8080]:Press Enter to accept the default for PORT. The CLI validates required fields and starts the build.
Watch the deployment status:
panda projects listOnce the build completes, the CLI outputs the live URL. Open it in a browser and append /health to verify the app is running.
Provision a managed PostgreSQL database
The example above assumes you already have a DATABASE_URL. If you need a database, PandaStack provisions managed PostgreSQL instances that auto-wire to your app.
panda databases create \
--name fiber-db \
--engine postgres \
--version 16This creates a PostgreSQL 16 instance on the free tier with a small storage volume. The CLI outputs the connection string:
DATABASE_URL: postgres://postgres:generatedpass@fiber-db.internal:5432/postgresLink the database to your Fiber app:
panda projects env set DATABASE_URL="postgres://postgres:generatedpass@fiber-db.internal:5432/postgres" --project fiber-apiRedeploy to inject the new variable:
panda projects deploy fiber-apiThe app now connects to the managed database. The free tier includes one database, seven days of backup retention, and a 50-connection limit — enough for development and small production workloads. Paid plans increase retention to 15 or 30 days and raise the connection limit to 300 or 1000.
Redeploy after changing environment variables
If you rotate JWT_SECRET or change the database connection string, update the variable and trigger a redeploy:
panda projects env set JWT_SECRET="newSecretKeyHere" --project fiber-api
panda projects deploy fiber-apiThe CLI redeploys the last successful build with the updated environment. This is faster than a full rebuild because it skips the go build step and only restarts the container with new configuration.
For debugging, check the live logs in the dashboard Logs tab. The CLI's panda projects logs command is currently unreliable for real-time tailing, so the dashboard is the better option for live troubleshooting.
Why this workflow matters
Every deployment platform eventually needs environment variables, but most wait until after the first failed deploy to tell you. pandastack.json inverts this: it declares dependencies upfront, validates them before building, and prevents the "it built successfully but does not run" class of failures.
The file also doubles as documentation. A new developer cloning the repo sees exactly which variables the app expects and what format they should take. That same file drives the deploy screen, so the documentation cannot drift out of sync with the actual deployment requirements.
For a team shipping multiple Fiber APIs, committing pandastack.json to each repo standardizes the deployment process. The same structure works for Node.js, Python, and other auto-detected languages, so the deploy workflow stays consistent across polyglot projects.
If you are migrating from Heroku or Render, pandastack.json's env array behaves like a combination of Heroku's app.json and Render's Blueprint environment section. The difference is that it prompts during deploy instead of requiring a separate configuration file or dashboard step.
Start with the free tier: five container apps, five static sites, one database, and 300 build minutes per month. For production workloads, the Pro plan at $15 per month adds 1000 build minutes, 500 GB bandwidth, and 15-day backup retention.
References
- [Go Fiber documentation](https://docs.gofiber.io/)
- [pgx PostgreSQL driver](https://github.com/jackc/pgx)
- [PandaStack environment variables guide](https://docs.pandastack.io/projects/env)
- [PandaStack CLI commands](https://docs.pandastack.io/cli/commands)