Ending an Open Source project does not end your responsibility to the people who relied on it. In education, accessibility, security, and civic technology, users may have built real workflows around your code. Some may not have paid staff, spare budget, or deep technical experience.
A migration guide helps those users leave safely. It does not promise ongoing maintenance. It gives people a map: what to replace, what to save, what may break, and where to go next.
This is part of ending well. Software for Progress Foundation supports Open Source developers because useful tools should reach the people who need them. When a project reaches the end of its life, a clear migration guide can protect that public benefit instead of letting it disappear suddenly.
Step 1: Say Who the Guide Is For
Do not write a migration guide for an imaginary expert user. Name the real groups you are trying to help.
For example:
- Small schools running your app on one shared server.
- Nonprofits using your database export for client services.
- Accessibility users who depend on specific keyboard or screen reader behavior.
- Security teams that integrated your tool into automated checks.
This helps readers quickly decide whether the guide applies to them. It also helps you avoid writing a huge document that tries to solve every possible migration path.
A simple opening is enough:
This guide is for current users of ProjectName who need to move away from it before support ends. It focuses on self-hosted installs used by small teams and community organizations.
Step 2: List What Must Be Moved
Before naming alternatives, describe what users need to take with them. Many migration failures happen because people move the obvious files but lose configuration, accounts, logs, or local changes.
Create a plain checklist:
- Application data
- User accounts and roles
- Uploaded files or media
- Configuration values
- API tokens or integration settings
- Custom themes, plugins, or patches
- Audit logs or reports users may need later
- Documentation specific to their installation
If your project handles sensitive data, say so plainly. Do not give legal advice unless you are qualified to do that. Instead, remind users to follow their own data retention, privacy, and security requirements before deleting or moving anything.
Step 3: Separate Export Steps From Replacement Choices
A good migration guide has two different jobs. First, it helps users get their data out. Second, it helps them choose where that data might go.
Keep those sections separate. Users may need an export even if they have not picked a replacement yet.
Your export section should include:
- The last version of the project that supports the export command.
- The exact command or admin screen to use.
- The format of the export, such as JSON, CSV, SQL, ZIP, or plain files.
- How to confirm the export worked.
- Common errors and what they mean.
For example:
Run projectname export --format json --include-uploads. Confirm that the output folder contains data.json, users.json, and uploads.zip. If uploads.zip is missing, check file permissions on the uploads directory before trying again.
This kind of detail matters. It gives a tired maintainer fewer support requests, and it gives users a better chance of leaving safely.
Step 4: Name Replacement Options Carefully
You do not need to officially endorse another project. You can still help users understand their options.
For each possible replacement, include practical notes:
- Whether it is Open Source, hosted, self-hosted, or commercial.
- Which features are similar.
- Which features are missing.
- Whether your export format can be imported directly.
- Any known accessibility or security differences you have observed.
- The level of technical effort likely required.
Be honest about uncertainty. It is better to write “We have not tested this path” than to imply confidence you do not have.
A useful replacement table can be written as bullets:
- Option A: Best fit for teams that need self-hosting. Import requires a custom script. Does not support our old reporting format.
- Option B: Best fit for users who want a hosted service. Not Open Source. Review pricing and data policies before moving.
- Option C: Best fit for developers who can adapt code. Similar license and architecture, but smaller community.
The goal is not to pick for your users. The goal is to reduce confusion.
Step 5: Include One Worked Example
A concrete example is often more useful than a long list of possibilities.
Imagine an Open Source reading practice app used by after-school programs. The project is ending because there are no active maintainers. A migration guide might include this example:
- Current setup: One community center runs the app on a low-cost server for 80 students.
- Data to save: Student names, reading levels, progress history, teacher notes, and uploaded reading materials.
- Export path: Use the final release to export student progress as CSV and uploaded files as a ZIP archive.
- Replacement path: Move reading materials into a shared folder and import progress CSV files into a spreadsheet while evaluating a new learning platform.
- Risk: Teacher notes may contain sensitive information, so the center should restrict access to the exported files.
- Verification: Check five student records before shutting down the old app.
This example does not solve every migration. But it shows users how to think: identify data, export it, protect it, test it, and only then retire the old system.
Step 6: Explain What Will Not Migrate
Users need to know what they may lose. Avoid soft language that hides real limits.
Create a section called What Will Not Transfer or Known Migration Gaps.
Common gaps include:
- Password hashes that cannot be imported into another system.
- Plugin settings with no equivalent elsewhere.
- Historical reports that only existed inside your app.
- Custom workflows built around undocumented behavior.
- Links that will break after the old service or domain goes away.
This may feel uncomfortable to write, but it builds trust. People can plan around known gaps. They cannot plan around silence.
Step 7: Set a Support Boundary
A migration guide should not quietly turn into permanent support. Be clear about what help, if any, is still available.
You might say:
Maintainers are not able to provide one-on-one migration support. We will accept documentation corrections until December 15, 2026, but we are not reviewing custom migration scripts or debugging new installations.
This protects maintainers from burnout while still leaving room for useful improvements. If community members want to add notes about a successful migration path, tell them how to suggest edits.
Step 8: Put the Guide Where Users Will Find It
A migration guide only helps if people can find it before they are stuck.
Link it from:
- The project README.
- The documentation home page.
- The final release notes.
- The archived website, if one exists.
- The issue tracker status message.
- The package registry description, if supported.
Use direct language in the link text: Migration guide for users leaving ProjectName. Avoid vague labels like Important update.
TL;DR
A project sunset is not just about stopping work. It is also about helping people land safely.
- Name who the migration guide is for.
- List the data, files, settings, and history users need to move.
- Give clear export steps before discussing replacements.
- Describe replacement options without pretending to know more than you do.
- Include one realistic example for a public benefit use case.
- Say what will not migrate.
- Set honest support boundaries.
- Put the guide everywhere users are likely to look.
Ending a project well is part of Open Source care. A clear migration guide helps your work keep serving people, even after the project itself is done.