Flysystem: one PHP interface for local, S3, SFTP and WebDAV storage
Abstraction for local and remote filesystems
At a glance
- What is it?
- Flysystem 3.x is a PHP file storage library that puts local disks, AWS S3, AsyncAws S3, SFTP, FTP, Google Cloud Storage, MongoDB GridFS, WebDAV and Zip archives behind a single Filesystem API. This review covers the mechanism, the install path, the adapter model and where it stops being the right tool.
- Who is it for?
- Adopt Flysystem when a PHP application must write to more than one storage backend, or when you want to swap local disk for S3 without rewriting call sites. Do not adopt it for POSIX operations the Filesystem API does not model, such as file locking, permissions or atomic rename.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 28 days ago.
- What is it written in?
- Mainly PHP, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem Flysystem solves for PHP applications
PHP's native filesystem functions assume a local disk. The moment an application stores uploads in S3, ships files to an SFTP partner or reads from a WebDAV share, that assumption breaks, and the code that handled local paths has to be rewritten around a vendor SDK. Flysystem's answer is an interface: the README describes it as "one interface to interact with many types of filesystems", with adapters translating that interface into the calls each backend actually understands.
The intended reader is a PHP developer or a framework integrator, not someone who wants a filesystem abstraction in another language. The topic list and the README both point at PHP, and the minimum runtime stated in the README badge is PHP 8.0.2. Frameworks sit on top rather than beside it: the related-searches list includes Laravel Flysystem, flysystem symfony and Flysystem Drupal, which reflects that these ecosystems consume the library instead of replacing it.
The practical payoff is portability of application code. If your upload handler talks to a Flysystem Filesystem, changing the storage backend becomes a change of adapter and configuration, not a change of every call site. That is the whole pitch, and it is a narrow one. Flysystem is not a database, not a queue, and not a CDN. It moves and inspects files.
How the Filesystem and adapter split actually works
The architecture is two layers. The Filesystem object is what application code calls; the adapter is what performs the work. The README links to an architecture page and a Filesystem API page rather than inlining the details, so the shape has to be read from the repository layout and the adapter list.
The officially supported adapters named in the README are Local, FTP, SFTP, Memory, AWS S3, AsyncAws S3, Google Cloud Storage, MongoDB GridFS, WebDAV and ZipArchive. That list is the clearest statement of scope. Each adapter is a separate package, which means the core library stays small and the vendor SDK for a given backend is only pulled in when you install that adapter. The third-party list extends the same pattern to Azure Blob Storage, GitLab, Google Drive, BunnyCDN, SharePoint and OneDrive via MS Graph, Dropbox, Uploadcare and others.
Adapters can also compose. The third-party section names a ReplicateAdapter, and a separate project, FlysystemUsefulAdapters, offers FallbackAdapter, LogAdapter, ReadWriteAdapter and RetryAdapter. Those are decorators: they take an adapter and change how it behaves without the application knowing. The README also points to a guide for creating an adapter yourself, which is the escape hatch when no existing adapter matches a backend.
The repository layout confirms the split. src/ holds the library, test_files/ holds fixtures, and docker-compose.yml brings up the services the test suite needs: MongoDB on 27017, a SabreDAV server on 4040, a WebDAV container on 4080, SFTP on 2222 and 2223, and FTP servers on 2121 and 2122. That compose file is a statement about how the adapters are verified: against real servers, not mocks alone.
Installing Flysystem and writing to a local disk
Flysystem installs through Composer. The README does not print an install command; the package name comes from the repository and the adapter list, where league/flysystem is the core and each backend is a separate adapter package named in the README's adapter links. The README badge states the minimum PHP version as 8.0.2.
The README's Getting Started section points at the documentation site for the Filesystem API and the adapter pages rather than giving a snippet, so there is no install or usage example to copy from the repository files. The shape the documentation describes is: construct an adapter, wrap it in a Filesystem, then call methods on the Filesystem. Because no such snippet appears in the README or the repository files, none is reproduced here; read the Filesystem API page and the adapter page for your backend before writing code.
One caution about the install path: the README's version badge and the release list do not agree on their own. The releases shown are 3.16.0 from 2023-09-07, 3.0.0 from 2022-01-14 and 2.0.4 from 2021-04-05, while the repository's last push is 2026-09-02. The 3.x branch is receiving commits, but the tagged releases listed are old. Pin a version you have actually resolved and read the CHANGELOG.md in the repository rather than assuming the tag list reflects current work.
Where Flysystem is the wrong tool
The abstraction is a lowest-common-denominator interface, and that is a real cost. The Filesystem API models reading, writing, listing, checking existence and reading metadata. It does not model file locking, POSIX permission bits, hard links, symlinks or atomic rename semantics. If your application depends on any of those, an adapter will either not expose them or will expose them with backend-specific behaviour that differs from a local disk. For a job that is genuinely local-only, plain PHP filesystem functions are simpler and have no adapter layer in the way.
Backend behaviour also leaks through in places the interface cannot hide. The related-searches list includes Flysystem mimetype, which points at a known friction point: MIME type detection depends on what the backend reports, and a remote store may report less than a local disk does. Metadata calls against S3 or WebDAV can be network round trips, so code that checks existence in a loop will be slow in a way it would not be on a local disk.
The third-party adapter list is another boundary. Azure Blob Storage, Dropbox, Google Drive and OneDrive adapters live outside the repository and outside the maintainer's release process. The README links to them, but their compatibility with a given 3.x release is not something the core project guarantees. If your storage is one of those, you are depending on a separate maintainer.
Finally, the documentation is spread across a separate site. The README is a set of links, not a reference. Anything specific about an adapter's options, error behaviour or credential handling has to be read on the documentation site or in the adapter's own source.
Flysystem compared with talking to each SDK directly
The real alternative is not another abstraction layer. It is calling the vendor SDK directly: the AWS SDK for PHP for S3, phpseclib or the ssh2 extension for SFTP, a WebDAV client for WebDAV. That approach gives you the full surface of each backend, including the operations Flysystem's interface does not model, and it removes a dependency from the request path.
The difference is where the variation lives. With direct SDK calls, every backend has its own call sites, its own error types and its own credential handling, and switching backends means rewriting those call sites. With Flysystem, the variation is pushed into the adapter, and application code sees one API. You pay for that with the operations the interface cannot express.
There is a middle position worth naming. Flysystem's own adapter list includes AsyncAws S3 alongside AWS S3, so the same storage backend can be reached through two different SDKs depending on which one you already depend on. And the decorator adapters from the third-party list, such as FallbackAdapter and RetryAdapter, are things you would otherwise hand-roll around direct SDK calls. If your application already needs retries and fallbacks, the decorator model is the part of Flysystem that is hardest to reproduce cheaply.
The choice comes down to how many backends you actually touch. One backend, one SDK, call it directly. Two or more, or a realistic chance of switching, and the adapter layer earns its place.
Maintenance, upgrade cost and the MIT licence
The repository is not archived, and the last push was on 2026-09-02. That is recent enough that the 3.x branch is being worked on, but the tagged releases listed are older: 3.16.0 is dated 2023-09-07. Anyone evaluating this should treat the branch and the tags as two different signals and check CHANGELOG.md for what has landed since the last tag.
Upgrade cost is concentrated in major versions. The README links to a page about what is new in V2 and V3, and a separate page for upgrading from 1.x. The existence of a dedicated upgrade guide, and the fact that the release list jumps from 2.0.4 to 3.0.0, tells you the 2.x to 3.x transition is not a drop-in. Budget for reading that guide before moving a production application.
Adapter versioning adds a second axis. The core library and each adapter are separate Composer packages, so an upgrade means checking that the adapter you use has a release compatible with the core version you are moving to. Third-party adapters are outside that process entirely, and the README's third-party section is a list of links, not a compatibility matrix.
The licence is MIT, as stated in the README badge and the LICENSE file. MIT is permissive: it allows use in closed-source and commercial applications, and it requires that the copyright notice and permission notice be included. That is a description of the licence text, not legal advice. If your organisation has rules about attribution in distributed software, the MIT notice requirement is the clause to check with whoever handles that.
Editorial conclusion
Adopt Flysystem when a PHP application must write to more than one storage backend, or when you want to swap local disk for S3 without rewriting call sites. Do not adopt it for POSIX operations the Filesystem API does not model, such as file locking, permissions or atomic rename. Before committing, verify two things: that the adapter for your backend is in the officially supported list and matches the 3.x branch, and that your PHP runtime satisfies the minimum version the README states.
Frequently asked questions
What is Flysystem in PHP?
It is a file storage library for PHP that provides one interface for interacting with many types of filesystems, so application code does not have to be written against a specific vendor SDK. The README states the goal is a consistent experience whichever storage you choose.
How do I install Flysystem?
Through Composer. The core package is league/flysystem, and each backend is a separate adapter package named in the README's adapter list, such as the AWS S3, SFTP or FTP adapter. The README states a minimum PHP version of 8.0.2.
Which storage backends does Flysystem support?
The officially supported adapters listed in the README are Local, FTP, SFTP, Memory, AWS S3, AsyncAws S3, Google Cloud Storage, MongoDB GridFS, WebDAV and ZipArchive. Azure Blob Storage, Dropbox, Google Drive, OneDrive and others are third-party adapters maintained outside the repository.
Can I use Flysystem with S3 and switch to a local disk later?
That is the point of the adapter model. Application code calls the Filesystem object, and the backend is chosen by which adapter you construct and pass to it, so changing storage means changing the adapter and its configuration rather than the call sites.
What is a file storage system?
In this context it is the backend that holds files, whether a local directory, an object store such as S3, or a remote protocol server such as SFTP or WebDAV. Flysystem's role is to give PHP code one API across those backends instead of one API per backend.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/thephpleague-flysystem)