Skip to content

Best Practices

Performance Considerations

  • Optimize database queries to minimize load
  • Implement pagination for large data sets
  • Use async/await for I/O-bound operations
  • Monitor and optimize database indexes
  • Implement connection pooling for database connections
  • Consider partitioning strategies for large tables
  • Optimize geospatial queries using appropriate PostGIS functions
  • Use TimescaleDB hypertables for efficient time-series data storage and querying

Database Optimization

  • Use appropriate indexes for frequently queried fields
  • Optimize SQL queries for performance
  • Use database connection pooling
  • Implement caching for frequently accessed data
  • Monitor query performance and set up alerts for slow queries
  • Use EXPLAIN ANALYZE to identify performance bottlenecks

API Optimization

  • Use async/await for I/O-bound operations
  • Implement pagination for endpoints that return large datasets
  • Use appropriate HTTP status codes and headers
  • Implement rate limiting for public APIs
  • Use connection pooling for external API calls

Resource Management

  • Close database connections and file handles properly
  • Use context managers for resource cleanup
  • Monitor memory usage and optimize memory-intensive operations
  • Implement proper connection pooling for database access

Security Guidelines

  • Never store sensitive information in code repositories
  • Use environment variables for configuration
  • Implement proper authentication and authorization
  • Validate all user inputs using SQLModel
  • Protect against common web vulnerabilities (XSS, CSRF, SQL injection)
  • Use HTTPS for all communications
  • Implement rate limiting to prevent abuse
  • Regularly update dependencies to address security vulnerabilities
  • Apply principle of least privilege for database access
  • Implement data encryption for sensitive information

Input Validation

  • Validate all user inputs using Pydantic models (within SQLModel).
  • Implement strict type checking for API parameters.
  • Use parameterized queries to prevent SQL injection.

Authentication and Authorization

  • Implement API key authentication as specified in requirement #21.
  • Validate API keys for all protected endpoints.
  • Implement role-based access control for different user types.

Data Protection

  • Encrypt sensitive data in transit and at rest.
  • Implement proper error handling to avoid leaking sensitive information.
  • Follow the principle of least privilege for database access.

Error Handling and Logging Standards

Error Hierarchy:

  • Define a custom exception hierarchy for different error types
  • Use specific exception types for different error scenarios

Custom Exception Examples

# Base exception for all application-specific errors
class InfDBError(Exception):
    """Base exception for all InfDB-specific errors."""
    def __init__(self, message, details=None):
        super().__init__(message)
        self.details = details

# Domain-specific exceptions
class DatabaseConnectionError(InfDBError):
    """Raised when a database connection cannot be established."""
    pass

class GeospatialError(InfDBError):
    """Base exception for geospatial-related errors."""
    pass

class InvalidCoordinateError(GeospatialError):
    """Raised when invalid coordinates are provided."""
    pass

# Usage example
try:
    # Some operation that might fail
    result = repository.get_raster_center(building_id, resolution)
    if not result:
        raise InvalidCoordinateError(
            f"No raster found for building {building_id} at resolution {resolution}",
            details={"building_id": building_id, "resolution": resolution}
        )
except InvalidCoordinateError as e:
    # Handle the specific error
    logger.error(f"Coordinate error: {str(e)}", extra={"details": e.details})
    raise HTTPException(status_code=404, detail=str(e))
except DatabaseConnectionError as e:
    # Handle database connection errors
    logger.critical(f"Database connection failed: {str(e)}")
    raise HTTPException(status_code=503, detail="Service temporarily unavailable")
except InfDBError as e:
    # Handle any other application-specific errors
    logger.error(f"Application error: {str(e)}")
    raise HTTPException(status_code=500, detail=str(e))
except Exception as e:
    # Handle unexpected errors
    logger.exception(f"Unexpected error: {str(e)}")
    raise HTTPException(status_code=500, detail="An unexpected error occurred")

Error Messages

  • Provide clear, actionable error messages.
  • Include relevant context in error messages.
  • Use structured error responses for API endpoints:
    {
        "error": "Invalid weather parameter",
        "details": "Parameter 'temperature' is not available for the specified date range."
    }
    

Logging

  • Use the Python logging module for all logging
  • Configure appropriate log levels
  • Include relevant context in log messages (user ID, request ID, etc.)
  • Structure logs for easy parsing and analysis
  • Avoid logging sensitive information

Logging Levels:

  • DEBUG: Detailed information for debugging
  • INFO: Confirmation that things are working as expected
  • WARNING: Indication that something unexpected happened
  • ERROR: Due to a more serious problem, the software couldn't perform some function
  • CRITICAL: A serious error indicating the program may be unable to continue running

Log Format:

{timestamp} [{level}] {module}: {message} {context}