The release of Symfony 7.4 marks a pivotal moment for PHP developers, particularly those of us architecting high-performance, cloud-native applications. While the changelog is packed with the usual array of developer experience (DX) improvements and performance tweaks, one feature stands out as a game-changer for infrastructure teams and backend leads alike: the Share Directory.
For years, we’ve wrestled with the “Cache Dilemma” in multi-server environments. We’ve written hacky scripts, managed complex NFS mounts and accepted performance penalties — all to keep our application state synchronized. With Symfony 7.4, the core team has finally addressed this architectural friction point head-on.
In this artice, we will explore the new var/share directory, understand the critical problem it solves and implement a robust, production-ready configuration using Symfony 7.4, Doctrine and Flysystem.
To appreciate the elegance of the Share Directory, we must first revisit the pain of the past. In a standard Symfony application, the var/cache directory has historically been the dumping ground for two very different types of data:
Imagine you are deploying a Symfony app to a Kubernetes cluster with 10 pods.
We were stuck choosing between consistency and performance.
Symfony 7.4 introduces a dedicated architectural concept to solve this: the Share Directory.
This feature formally decouples the location of system-specific files from application-shared files.
This separation allows us to have the best of both worlds: blazing-fast, local system caches and a consistent, shared application state.
Let’s get our hands dirty. We will build a Symfony 7.4 application that leverages the Share Directory for three common use cases:
Ensure you are running PHP 8.2 or higher and have the Symfony CLI installed.
symfony new my_app --webapp cd my_app composer require symfony/framework-bundle:^7.4
In a fresh Symfony 7.4 installation, the framework is already aware of this concept. Open your .env file. You will see a new environment variable:
# .env APP_SHARE_DIR=$APP_PROJECT_DIR/var/share
Under the hood, the Kernel class now implements a getShareDir() method. If you are upgrading an existing application, you might need to add this manually or rely on the default fallback (which points to the cache directory for backward compatibility).
To enforce this structure in an upgraded app, update your Kernel.php if necessary, or simply define the environment variable.
The most immediate win is moving your application cache to the shared directory. By default, Symfony’s file system cache adapter saves to var/cache/pools. We want to move this to var/share/pools.
Open config/packages/cache.yaml. We will configure the default app cache to use the new %kernel.share_dir% parameter.
# config/packages/cache.yaml framework: cache: # distinct_id helps avoid collisions if multiple apps share the same storage prefix_seed: 'my_app_%env(APP_ENV)%' # Default app cache app: cache.adapter.filesystem # System cache (stays in var/cache, FAST!) system: cache.adapter.system # Configure filesystem adapter to use the share directory default_redis_provider: 'redis://localhost' pools: # We explicitly tell the 'cache.app' pool to use the share directory cache.app: adapter: cache.adapter.filesystem provider: ~ # The 'directory' option is available for the filesystem adapter # We use the new container parameter default_lifetime: 3600 provider: 'cache.default_marshaller' services: # We need to configure the specific directory for the filesystem adapter # Since we can't easily pass the directory in the simplified YAML above for the main adapter, # we can define a custom adapter or rely on the global default if Symfony 7.4 automates it. # However, for explicit control, let's define a shared pool: cache.adapter.shared_filesystem: parent: 'cache.adapter.filesystem' tags: ['cache.pool'] arguments: $directory: '%kernel.share_dir%/pools' framework: cache: app: cache.adapter.shared_filesystem
In standard Symfony 7.4, the default filesystem adapter might still default to cachedir. By explicitly creating a service cache.adapter.sharedfilesystem pointing to %kernel.share_dir%/pools, we ensure that our application cache is stored in the correct location.
To verify this, clear your cache and warm it up.
php bin/console cache:clear php bin/console cache:pool:clear cache.app
Then, generate some cache entries (e.g., by visiting a page). Check the directory structure:
ls -la var/share/pools
You should see a folder structure created by the cache adapter.
Handling user uploads in a cluster is a classic use case for shared storage. We will use league/flysystem-bundle to map a storage adapter to var/share/storage.
Installation:
composer require league/flysystem-bundle
Configuration: Open config/packages/flysystem.yaml.
# config/packages/flysystem.yaml flysystem: storages: default.storage: adapter: 'local' options: # Use the new kernel parameter directory: '%kernel.share_dir%/storage'
Now, let’s create a service to handle file uploads using this storage. We will use PHP 8 Attributes for dependency injection.
namespace App\Service; use League\Flysystem\FilesystemOperator; use Symfony\Component\DependencyInjection\Attribute\Target; use Symfony\Component\HttpFoundation\File\UploadedFile; class FileManager { public function __construct( #[Target('default.storage')] private readonly FilesystemOperator $storage ) {} public function uploadUserFile(UploadedFile $file, string $userId): string { $filename = sprintf('%s/%s.%s', $userId, uniqid(), $file->guessExtension()); $stream = fopen($file->getPathname(), 'r'); // Write to var/share/storage/... $this->storage->writeStream($filename, $stream); if (is_resource($stream)) { fclose($stream); } return $filename; } public function getFileContent(string $filename): string { return $this->storage->read($filename); } }
When you deploy this to Kubernetes, you will mount a Persistent Volume Claim (PVC) to /app/var/share. If Pod A uploads a file, it is written to the PVC. Pod B can immediately read that file via the same path, because they share the underlying storage volume.
While usually not recommended for heavy concurrent writes, using SQLite in var/share is a fantastic pattern for read-heavy, low-write data, or simple internal tooling dashboards that need to persist across deployments without a full MySQL/PostgreSQL setup.
Configuration: Open config/packages/doctrine.yaml.
doctrine: dbal: # Use the standard SQLite driver driver: 'pdo_sqlite' # Point the path to the share directory path: '%kernel.share_dir%/db/app.sqlite' charset: UTF8
Ensure the directory exists:
mkdir -p var/share/db
Now, when you run migrations:
php bin/console doctrine:migrations:migrate
The .sqlite file is created in the shared directory. All servers in your cluster will read from this single file.
Warning: SQLite over NFS (Network File System) can have locking issues. Ensure your shared storage solution supports file locking correctly (e.g., AWS EFS with appropriate mounting options), or reserve this for scenarios with very low write frequency.
To fully utilize this feature, your deployment manifest (e.g., docker-compose.yml or Kubernetes deployment.yaml) needs to be updated.
Here is how you simulate the production environment locally.
services: app_1: build: . environment: APP_SHARE_DIR: /app/var/share volumes: - shared_data:/app/var/share app_2: build: . environment: APP_SHARE_DIR: /app/var/share volumes: - shared_data:/app/var/share volumes: shared_data:
In this setup:
In Kubernetes, you would use a PersistentVolumeClaim.
apiVersion: apps/v1 kind: Deployment metadata: name: symfony-app spec: replicas: 3 template: spec: containers: - name: php image: my-symfony-app:7.4 env: - name: APP_SHARE_DIR value: "/var/www/html/var/share" volumeMounts: - mountPath: "/var/www/html/var/share" name: shared-storage volumes: - name: shared-storage persistentVolumeClaim: claimName: efs-pvc
Verification:
If you are maintaining a legacy application, adopting the Share Directory requires a few careful steps.
Symfony 7.4’s Share Directory is more than just a new folder structure; it is a maturity signal. It acknowledges that modern PHP applications live in the cloud, across clusters and need to scale horizontally without fighting the framework.
By adopting var/share, you simplify your infrastructure configuration, improve the performance of your system caches and provide a clear, standardized location for your application’s state.
Ready to scale? Start by upgrading a non-critical microservice to Symfony 7.4 today. Implement the var/share directory, remove those complex NFS mounts for your system cache and watch your average response times drop.
Keep in touch! Did this article help you clarify your upgrade path? Follow me on [LinkedIn:https://www.linkedin.com/in/matthew-mochalkin/]. Let’s build better software, together.
\


