DEV Community

Sandeep Illa
Sandeep Illa

Posted on

Error Handling and Logging: The Things That Save Your Backend

When you start learning backend development, it’s easy to focus on features, getting APIs to respond, connecting to the database, or just making it all work.
But once you deploy your first real app, you quickly realize:
things break, and when they do, your logs are your lifeline.

In my projects built with FastAPI, I follow a simple but consistent pattern for error handling.
Every critical API operation sits inside a try-except block, where I can capture specific exceptions and log them properly before returning a clean, user-friendly response.

For Example:

from fastapi import APIRouter
from sqlalchemy.exc import SQLAlchemyError
from app.logger import logger  # custom logger
from app.database import get_db
from app.models import Student

router = APIRouter()

@router.get("/students/{student_id}")
def get_student(student_id: int):
    try:
        db = get_db()
        student = db.query(Student).filter(Student.id == student_id).first()

        if not student:
            logger.warning(f"No student found with ID {student_id}")
            return {"error": "Student not found"}

        logger.info(f"Fetched student: {student.name}")
        return {"student": student.name, "email": student.email}

    except SQLAlchemyError as e:
        logger.error(f"Database error while fetching student {student_id}: {e}")
        return {"error": "Database connection failed"}

    except Exception as e:
        logger.error(f"Unexpected error in get_student API: {e}")
        return {"error": "Something went wrong, please try again later"}

Enter fullscreen mode Exit fullscreen mode

Here’s what’s really happening behind the scenes:

  • Every error is caught from database issues to unexpected runtime exceptions.

  • Logs are categorized info for successful events, warnings for missing data, and errors for critical issues.

  • No internal crash leaks to the user. Instead, users see a clean, friendly response while I get detailed error traces in my logs.

The logger I use writes all messages to a local file, but also integrates with CloudWatch for live monitoring when deployed.
This means I can track exactly what happened in production — even days later, without touching the live server.

It’s one of those invisible systems that keeps everything steady.
You won’t think much about logging when everything’s working fine but when something suddenly breaks, those logs become your best friend.

Over time, I’ve learned that a stable backend isn’t the one that never fails it’s the one that knows how to fail gracefully and tell you exactly why.

Top comments (0)