Contributing to Open Source
Table of Contents
Why Open Source Matters for Backend Developers
Open source is one of the best ways to grow from “I followed a tutorial” to “I can build and maintain real software.” For backend developers, it gives you:
- Real-world code to learn from
- Practice with collaboration and review
- Public evidence of your skills for employers
- A network of people who build serious systems
You do not have to be an expert to contribute. Many valuable contributions are small, focused, and done by beginners.
This chapter explains how to get from zero to your first and then your first few open source contributions, with concrete backend-focused examples.
Myths About Open Source
Before you start, it helps to remove a few common false beliefs.
Important: You do not need to be an expert, a “famous” programmer, or a library author to contribute to open source.
Some common myths:
| Myth | Reality |
|---|---|
| “I must write a big feature to contribute.” | Tiny fixes, docs, examples, tests, and typo corrections are all real contributions. |
| “Maintainers will be annoyed by beginners.” | Most projects welcome help, especially with documentation, tests, and bug triage. |
| “I need to understand the whole codebase first.” | You only need to understand the small part you are touching. Understanding grows over time. |
| “I must use Git perfectly.” | You only need the basics: clone, branch, commit, push, open PR. You will learn the rest while contributing. |
Choosing the Right Project
Picking a suitable project makes the difference between a frustrating experience and a great one.
Start with Your Tech Stack
You are learning backend development, so focus on projects that match what you are using:
Examples:
- Python backend frameworks:
- FastAPI
- Django
- Flask
- Database tools:
- SQLAlchemy
- Alembic
- psycopg (PostgreSQL driver)
- Supporting libraries:
- Pydantic
- HTTPX / Requests
- Celery
- Redis-py
- Dev tooling:
- pytest
- black, isort, flake8, ruff
- pre-commit
If you are already using a library in your learning projects, that is an excellent candidate. You know its basic behavior and docs needs.
Signs of a Beginner-Friendly Project
Look for these signals in a GitHub / GitLab repository:
| Signal | What to look for |
|---|---|
| License | A clear open source license, usually a LICENSE file. |
| Activity | Recent commits in the last 1–2 months. Open and closed pull requests. |
| Contribution guide | A CONTRIBUTING.md file. It explains how to contribute. |
| Code of conduct | A CODE_OF_CONDUCT.md file. It shows basic community rules. |
| Beginner tags | Issues labeled good first issue, beginner, help wanted, or similar. |
| Docs | A README.md that explains setup and development. |
If a repo has no license, you must assume you cannot legally use or modify the code.
Rule: Only contribute to repos that clearly state an open source license.
Start Small and Familiar
Good starting points:
- Tools you already installed:
- That FastAPI extension you used
- That Redis client you configured
- Small utilities:
- CLI tools that wrap Docker or PostgreSQL
- DevOps helpers like environment variable loaders
- Course-related repos:
- Example apps from tutorials that explicitly invite issues and PRs
Avoid at the beginning:
- Very large monorepos with dozens of services
- Very complex systems with many custom internal tools and processes
- Inactive projects with no response from maintainers
Types of Contributions You Can Make
You do not have to jump directly into implementing complex backend features. There are many ways to help.
Documentation Improvements
Documentation is often the easiest and most valuable entry point.
Examples you can contribute:
- Fix typos or grammar in
README.mdor docs - Clarify confusing explanations
- Add missing examples in Python for an API
- Add “Getting started” steps:
- “How to run the dev server with Docker”
- “How to set up PostgreSQL locally”
- Add code comments to tricky parts of examples
For instance, in a FastAPI extension library, you might add:
- A simple example for integrating with Redis
- An example for using dependency injection for a new middleware
Examples and Tutorials
As a beginner, you remember what was confusing. That is very valuable.
Examples you can add:
- “Minimal FastAPI + PostgreSQL + SQLAlchemy example”
- “Simple Celery + Redis background task example”
- “JWT authentication example with refresh tokens”
- “File upload and S3 storage example”
Often docs have a “Examples” or “Recipes” section. You can add a new page or expand an existing one with code you have already built in your practice projects.
Bug Reports and Reproduction
Good bug reports are a form of contribution.
A useful bug report often includes:
- Your environment:
- OS
- Python version
- Library versions
- Exact steps to reproduce:
- “Install this version”
- “Run this script”
- “Send this HTTP request”
- Expected vs actual behavior
- Minimal reproducible example
For a backend example, you might report:
- “When using PostgreSQL 16 with this ORM version, transactions fail with this error. Here is a small script that reproduces it.”
Small Code Fixes
Once you are comfortable reading a bit of code, you can:
- Fix simple bugs
- Update deprecated APIs
- Improve error messages
- Handle a missing edge case
Examples:
- Fix a FastAPI middleware that crashes if a header is missing, by checking for existence first
- Update a PostgreSQL connector to support a new error code
- Fix off-by-one errors in pagination helpers
Tests and Test Improvements
Tests are crucial in backend systems and often underdeveloped.
You can:
- Add tests for existing functions that currently have no tests
- Improve test coverage around critical parts like:
- Authentication handlers
- Database transaction scopes
- Caching behavior
- Convert ad-hoc scripts into proper tests with pytest
Example:
- A library has a database connection pool class with no tests for timeout behavior. You add tests for:
- “Raises timeout when all connections are busy”
- “Releases connections on exception”
Tooling and Quality Improvements
Many projects appreciate help with:
- Formatting configuration (black, isort, ruff)
- Pre-commit hooks
- Simple CI improvements:
- Add Python 3.12 to test matrix
- Fix failing tests on Windows or Linux
- Updating README badges (build status, coverage)
Start small to avoid breaking workflows.
Understanding the Project
Before touching code, invest a bit of time understanding how the project is structured.
Read the README and CONTRIBUTING
Look for:
- How to install dependencies
- How to run tests
- How to run the app (if it is a service)
- How they want contributions:
- “Open an issue first”
- “Fork and open a pull request”
- “Follow these coding standards”
If there is a CONTRIBUTING.md file, follow it literally. Many maintainers reject PRs that ignore it.
Rule: Always read and follow CONTRIBUTING.md before sending your first pull request.
Explore the Code Structure
Look at top-level folders:
| Folder | Typical contents in backend-related repos |
|---|---|
src/ or package name | Main Python code: modules, business logic, integrations. |
tests/ | Unit, integration, and API tests. |
docs/ | Documentation source: Markdown, Sphinx, MkDocs files. |
examples/ | Small runnable examples using the library. |
docker/ or compose/ | Dockerfiles, docker-compose configurations. |
alembic/ or migrations/ | Database migrations if it is a web app or ORM. |
For example, in a typical FastAPI project:
app/main.pymay define the FastAPI instanceapp/routers/may contain routers for different resourcesapp/models/may contain Pydantic models or ORM modelsapp/core/may contain configuration, security utilities, etc.
You do not need to read everything. Scan until you find the part relevant to your issue.
Run the Project or Tests Locally
Before changing code, make sure you can:
- Install dependencies:
pip install -e .[dev]or as described in the docs- Run tests:
pytestor as specified- For web apps, run the dev server:
uvicorn app.main:app --reloador similar
If tests do not pass on a fresh clone, check:
- Is there an open issue about test failures?
- Is your environment correct?
- Are you missing a database or service like Redis?
For complex apps, Docker Compose is common:
docker compose up -d
pytestFinding Good First Issues
Most projects label beginner-friendly tasks.
Using GitHub Issue Labels
Filter issues by common labels:
good first issuehelp wantedbeginnereasydocumentation
In GitHub, you can use the search bar like:
label:"good first issue" is:openlabel:"documentation" is:open
Example backend-related beginner issues:
- “Add example using Redis as a cache backend”
- “Clarify docs for JWT refresh token flow”
- “Add missing test for POST /users/ endpoint”
- “Fix pagination links in API docs”
Ask Before You Start
Many projects expect you to comment on an issue before working on it, especially if it is older.
A simple comment:
Hi, I am new to this project and would like to work on this issue. Is it still available?Wait for a response. This:
- Avoids duplicated work
- Gives maintainers a chance to provide hints or constraints
- Shows you respect the project’s process
If the issue is very old and there is no response after some time, you can still try, but be prepared that the maintainers may have moved on.
Working with Git for Contributions
You already know Git basics from earlier chapters. Here is how to apply them specifically to open source.
Fork, Then Clone
For most GitHub projects:
- Click “Fork” in the repository on GitHub.
- Clone your fork:
git clone https://github.com/your-username/project-name.git
cd project-name- Add the original repo as
upstream:
git remote add upstream https://github.com/original-owner/project-name.gitNow you can pull updates from the original:
git fetch upstream
git checkout main
git merge upstream/mainCreate a Branch per Contribution
Work on a separate branch for each issue or feature:
git checkout -b fix-pagination-linksSome projects like branches to reference issue numbers:
git checkout -b docs-jwt-refresh-#1234Keep branches small and focused. One PR per logical change is easier to review.
Make Small, Clear Commits
Each commit should represent a small logical change.
Examples of helpful commit messages:
Fix off-by-one error in pagination link generationAdd example for FastAPI + Redis cacheImprove JWT refresh token docsAdd tests for transaction rollback on error
Avoid vague messages like fix, changes, or stuff.
Run Tests and Linters Before Pushing
Maintain the project’s quality checks:
pytest
ruff check .
black .
Or whatever is described in CONTRIBUTING.md.
If tests fail, fix them first. Sending a PR with failing tests is usually not welcomed unless your PR is specifically about a failing test and you mention that clearly.
Making Your First Pull Request
Once your change is ready and tested, you can propose it for inclusion.
Push Your Branch
Push the branch to your fork:
git push origin fix-pagination-linksGitHub will show you a link to open a pull request.
Write a Clear PR Description
Your PR description should explain:
- What problem are you solving?
- What did you change?
- How can reviewers test it?
Template example:
## Summary
Fixes pagination links in the API docs so that the `next` and `previous` URLs use the correct `page` parameter.
## Changes
- Updated `generate_pagination_links` to use `page + 1` and `page - 1` correctly.
- Added tests for `page=1` and `page=last_page` cases.
- Updated documentation example to show correct links.
## Testing
- `pytest tests/test_pagination.py` (passes)If your PR fixes a specific issue, link it:
Fixes #1234.GitHub will then automatically close the issue if the PR is merged.
Be Polite and Open to Feedback
Maintainers review your PR voluntarily. They may:
- Ask you to change things:
- Naming
- Code style
- Design choices
- Request extra tests or docs
- Decline the PR if it does not match their roadmap
Treat their review like free mentoring. Ask clarifying questions when needed.
Example response to review:
Thanks for the feedback! I updated the variable names and added the extra test you suggested. Please take another look.Common Contribution Patterns for Backend Projects
Here are some realistic backend-specific contribution ideas you can look for.
Improving Error Messages
Many backend libraries have cryptic errors.
Examples you can implement:
- In an ORM:
- If a required environment variable (like
DATABASE_URL) is missing, raise a clear error: - “DATABASE_URL is not set. Please set it to a valid PostgreSQL URL.”
- In a FastAPI extension:
- If a required dependency is not installed, show:
- “Install
python-jose[cryptography]to use JWT authentication.”
Changes often involve:
- Checking inputs at the start of functions
- Raising
ValueErroror custom exceptions with helpful messages - Adding tests for these error cases
Adding a Simple Endpoint Example
In a backend framework or plugin repo, you might add:
- An example
GET /healthendpoint - An example
GET /metricsendpoint that returns simple stats - A small
POST /itemsendpoint showing validation with Pydantic models
Example FastAPI snippet that you could contribute to a docs section:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.post("/items/")
async def create_item(item: Item):
return {"id": 1, **item.dict()}This kind of example helps new users understand how to use the library.
Improving Database Documentation
Database integrations often confuse beginners. You can improve docs by:
- Adding a section “Configuring PostgreSQL in Docker” with:
- A minimal
docker-compose.ymlexample - Connection URL example
- Explaining common connection errors:
- “Connection refused”
- “Authentication failed”
Example documentation snippet you might add:
version: "3.9"
services:
db:
image: postgres:16
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: app_db
ports:
- "5432:5432"And a Python connection example:
DATABASE_URL = "postgresql+psycopg://app:secret@localhost:5432/app_db"Adding Tests for Critical Backend Behaviors
Backend libraries often lack tests in these areas:
- Transaction rollback on exceptions
- Connection pool exhaustion handling
- Cache invalidation logic
- Rate limiting edge cases
You can write tests that:
- Trigger an exception in a transaction decorator and assert that data was not written
- Open many connections and confirm the pool blocks or times out as expected
- Check that
cache.setfollowed bycache.invalidatereally changes behavior
Building a Visible Open Source Profile
Your contributions can help your career if others can see and understand them.
Organize Your GitHub Profile
You do not need to be perfect, but a few things help:
- A short bio:
- “Backend developer, Python / FastAPI / PostgreSQL.”
- A link to your website or portfolio if you have one
- Pinned repositories:
- Your main practice projects
- Repos where you made meaningful contributions
Make Contributions Discoverable
When you apply for backend roles, you can mention:
- “Contributed tests and docs to [project-name].”
- “Implemented small bug fixes in [ORM or framework].”
- “Improved error messages and examples for [FastAPI plugin].”
In your CV or portfolio, link to:
- Specific PRs you are proud of
- Issues you opened that show deep understanding
Example entry:
| Project | Type | Contribution |
|---|---|---|
| FastAPI Extension X | Open source | Added Redis-backed session example, improved docs for JWT usage, and wrote tests for session expiration. |
Staying Involved and Growing
Your first contribution is the start, not the end.
Follow Project Activity
You can:
- Watch the repository on GitHub
- Subscribe to notifications for:
- Issues you opened
- PRs you created
- Read discussions to see how maintainers think
Over time you learn:
- How design decisions are made
- How to handle breaking changes
- How to communicate about performance and security concerns
Move from “User” to “Contributor” to “Maintainer”
A rough path you can follow:
- User
- Use the library in your personal projects.
- Report bugs, ask questions.
- Occasional contributor
- Fix a few issues.
- Improve docs and tests.
- Implement small features.
- Regular contributor
- Help triage issues (label them, ask for more info).
- Review small PRs from others if the maintainers allow it.
- Help answer questions in discussions.
- Potential maintainer
- Consistently contribute high-quality changes.
- Understand the codebase, tests, and release process.
- Sometimes maintainers invite such people to join the team.
You do not have to aim for maintainer status. Even a handful of helpful contributions can significantly improve your skills and resume.
Practical Step-by-Step Plan
Here is a simple sequence you can follow to get from zero to your first contributions.
Step 1: Pick One Library You Already Use
Examples:
- FastAPI
- SQLAlchemy
- Pydantic
- A FastAPI plugin you used in a course project
Visit its GitHub repo.
Step 2: Read README, CONTRIBUTING, and Open Issues
- Confirm the license
- See how to run tests
- Filter issues:
label:"good first issue"label:"documentation"
Pick one small issue that you understand.
Step 3: Fork, Clone, and Run Tests
- Fork the repo on GitHub
- Clone your fork
- Install dependencies as described
- Run tests to ensure your environment is correct
Step 4: Comment on the Issue
Post a short comment:
Hi, I am learning backend development and would like to work on this issue. Is it still open?Wait for confirmation if the project is active.
Step 5: Implement a Small, Focused Change
- Create a branch
- Make the change:
- Code
- Docs
- Tests
- Run tests and linters
- Commit with a clear message
Step 6: Open a PR and Respond to Feedback
- Push your branch
- Open a pull request
- Describe your change clearly
- Update your PR based on reviewer comments
Step 7: Reflect and Repeat
After your PR is merged or closed:
- What did you learn?
- Code style
- Testing patterns
- Design decisions
- What could you do next?
- Another small issue
- A test improvement
- A small example or doc clarification
Over time, you will gain:
- Confidence working in unfamiliar codebases
- A better understanding of real-world backend patterns
- Evidence of your skills that you can show to employers
Contributing to open source is one of the most effective ways to grow as a backend developer. Start small, be consistent, and treat every review as a free lesson from someone more experienced.
Views: 9
KAHIBARO