Overview
This guide covers critical production configuration, security best practices, and performance optimization techniques for your Go + React scaffold application.
Security Best Practices
Environment Variables and Secrets
Never commit sensitive data to version control:
.env files containing secrets
API keys and credentials
Database passwords
JWT session keys
Session Key Security
The SESSION_KEY is used for JWT token signing. Generate a strong, cryptographically secure random key:
# Generate a secure random key
openssl rand -base64 32
Use this value for your SESSION_KEY environment variable in production.
Password Security
The scaffold uses bcrypt with a cost factor of 14 for password hashing:
// From backend/auth implementation
bcrypt . GenerateFromPassword ([] byte ( password ), 14 )
Bcrypt cost factor of 14 provides a good balance between security and performance. In 2026, this remains secure for most applications.
JWT Token Security
Best practices for JWT tokens:
Use strong signing algorithms (HS256 or RS256)
Set reasonable expiration times (e.g., 24 hours)
Implement token refresh mechanisms for longer sessions
Store tokens securely on the client (httpOnly cookies preferred over localStorage)
Validate tokens on every protected route
Always validate and sanitize user inputs to prevent injection attacks:
MongoDB query injection
XSS (Cross-Site Scripting)
SQL injection (if using SQL databases)
The Echo framework provides built-in validation:
// Validate inputs before processing
if err := c . Bind ( & user ); err != nil {
return c . JSON ( http . StatusBadRequest , map [ string ] string {
"error" : "Invalid input" ,
})
}
// Validate required fields
if user . Email == "" || user . Password == "" {
return c . JSON ( http . StatusBadRequest , map [ string ] string {
"error" : "Email and password are required" ,
})
}
MongoDB Query Safety
Sanitize MongoDB queries to prevent NoSQL injection:
// Use typed queries with bson.M
filter := bson . M { "email" : email }
// Avoid directly interpolating user input into queries
// Bad: bson.M{"$where": userInput}
// Good: bson.M{"field": sanitizedInput}
CORS Configuration
Configure CORS properly for production. Do not use wildcard (*) origins in production.
Update your CORS middleware for production:
e . Use ( middleware . CORSWithConfig ( middleware . CORSConfig {
AllowOrigins : [] string {
"https://yourfrontend.com" ,
"https://app.yourfrontend.com" ,
},
AllowMethods : [] string { http . MethodGet , http . MethodPost , http . MethodPut , http . MethodDelete },
AllowHeaders : [] string { "Authorization" , "Content-Type" },
AllowCredentials : true ,
}))
HTTPS/TLS
Always use HTTPS in production. HTTP transmits data in plain text, exposing sensitive information.
Options for enabling HTTPS:
Reverse Proxy (Recommended) : Use nginx or Caddy to handle TLS termination
Let’s Encrypt : Free SSL/TLS certificates
Cloud Provider : Use built-in SSL/TLS (AWS ALB, Cloudflare, etc.)
Secure Session Cookies
If using cookies for authentication:
cookie := & http . Cookie {
Name : "session" ,
Value : token ,
HttpOnly : true , // Prevent JavaScript access
Secure : true , // Only send over HTTPS
SameSite : http . SameSiteStrictMode , // CSRF protection
MaxAge : 86400 , // 24 hours
}
c . SetCookie ( cookie )
Database Connection Pooling
MongoDB driver handles connection pooling automatically. Configure for production:
clientOptions := options . Client ().
ApplyURI ( mongoURI ).
SetMaxPoolSize ( 100 ). // Max connections
SetMinPoolSize ( 10 ). // Min connections
SetMaxConnIdleTime ( 60 * time . Second )
Context Timeouts
Always use context timeouts for database operations to prevent hanging requests:
ctx , cancel := context . WithTimeout ( context . Background (), 10 * time . Second )
defer cancel ()
result := collection . FindOne ( ctx , filter )
The scaffold currently uses context.TODO() - update to context.WithTimeout() for production.
Graceful Shutdown
Implement graceful shutdown to handle in-flight requests:
quit := make ( chan os . Signal , 1 )
signal . Notify ( quit , os . Interrupt , syscall . SIGTERM )
go func () {
if err := e . Start ( ":8080" ); err != nil && err != http . ErrServerClosed {
e . Logger . Fatal ( "shutting down the server" )
}
}()
<- quit
ctx , cancel := context . WithTimeout ( context . Background (), 10 * time . Second )
defer cancel ()
if err := e . Shutdown ( ctx ); err != nil {
e . Logger . Fatal ( err )
}
Build Optimization
Vite automatically optimizes production builds:
Code splitting
Tree shaking
Minification
Asset optimization
Lazy Loading
Implement code splitting for large applications:
import { lazy , Suspense } from 'react' ;
const Dashboard = lazy (() => import ( './Dashboard' ));
function App () {
return (
< Suspense fallback = {<div>Loading ...</ div > } >
< Dashboard />
</ Suspense >
);
}
Asset Optimization
Compress images before deployment
Use WebP format for images
Enable gzip/brotli compression on your web server
Implement CDN for static assets
Monitoring and Logging
Backend Logging
Echo includes logging middleware:
e . Use ( middleware . Logger ())
For production, consider structured logging:
import " github.com/sirupsen/logrus "
log := logrus . New ()
log . SetFormatter ( & logrus . JSONFormatter {})
log . SetLevel ( logrus . InfoLevel )
Error Tracking
Integrate error tracking services:
Sentry
Rollbar
Bugsnag
New Relic
Health Monitoring
Implement comprehensive health checks:
e . GET ( "/health" , func ( c echo . Context ) error {
// Check database connection
ctx , cancel := context . WithTimeout ( context . Background (), 5 * time . Second )
defer cancel ()
if err := db . Ping ( ctx , nil ); err != nil {
return c . JSON ( http . StatusServiceUnavailable , map [ string ] string {
"status" : "unhealthy" ,
"reason" : "database connection failed" ,
})
}
return c . JSON ( http . StatusOK , map [ string ] string {
"status" : "healthy" ,
"version" : "1.0.0" ,
})
})
Environment-Specific Configuration
Use the APP_ENV variable to enable environment-specific behavior:
if os . Getenv ( "APP_ENV" ) == "production" {
// Production-specific configuration
e . Debug = false
// Enable additional security middleware
// Configure production logging
}
Database Backups
Implement regular database backups. Data loss can be catastrophic.
MongoDB Backup Strategies
MongoDB Atlas : Automatic backups with point-in-time recovery
mongodump : Manual backup utility
mongodump --uri= "mongodb://localhost:27017" --out=/backups/$( date +%Y%m%d )
Replica Sets : Provide redundancy and high availability
Rate Limiting
Protect your API from abuse with rate limiting:
import " github.com/labstack/echo-contrib/middleware "
e . Use ( middleware . RateLimiter ( middleware . NewRateLimiterMemoryStore ( 20 )))
Production Checklist
Next Steps
Deployment Learn how to deploy your application
Coding Standards Review code style guidelines and best practices