Vortos
Object Store

Object Store

First-class object storage for Vortos with Cloudflare R2 defaults, S3-compatible semantics, direct uploads, lifecycle cleanup, outbox promotion, and observability.

Object Store

vortos/vortos-object-store is the first-class object storage package for Vortos. It uses S3-compatible semantics so Cloudflare R2, AWS S3, and other compatible providers can share one application contract.

The package is optimized for the default enterprise upload path: the backend creates short-lived upload intent objects, browsers upload directly to object storage, and command handlers promote validated temporary files to permanent keys through an outbox.

Direct-to-cloud is the default design

Large public uploads should not stream through PHP workers. The backend issues a presigned upload URL or POST policy, then stores object keys. This keeps web workers available under heavy upload traffic.

What The Package Covers

  • S3-compatible driver with Cloudflare R2 defaults.
  • Typed object keys, content types, metadata, byte ranges, upload constraints, and presigned URLs.
  • Direct upload lifecycle: create intent, promote temporary object, abort temporary object.
  • Transactional object-store outbox for writes, deletes, copies, moves, promotions, and aborts.
  • Explicit service interfaces for transactional, standalone async, and immediate provider behavior.
  • Temporary upload lifecycle rule planning and application.
  • Trusted server-side multipart transfers for backend-owned streams and files.
  • Circuit breaker for fast-fail protection when the provider is unavailable.
  • Provider exception mapping into Vortos exceptions.
  • Logging, tracing, and metrics with global and section-level opt-outs.
  • Testing fake for application tests.

Provider Strategy

The package exposes S3 bucket semantics intentionally. R2 is S3-compatible for object APIs, and AWS S3 remains the broadest interoperability contract in the object storage ecosystem.

The result is one Vortos API:

use Vortos\ObjectStore\Contract\ObjectStoreInterface;

$object = $objects->head('assets/invoices/inv-1001.pdf');

and provider-specific configuration at the edge:

$config
    ->driver('s3')
    ->provider('r2')
    ->region('auto')
    ->bucket($_ENV['OBJECT_STORE_BUCKET']);

Documentation Map

Service Guarantees

The injected interface is the delivery guarantee.

use Vortos\ObjectStore\Contract\ObjectStoreInterface;
use Vortos\ObjectStore\Contract\DirectUploadManagerInterface;
use Vortos\ObjectStore\Contract\StandaloneObjectStoreInterface;
use Vortos\ObjectStore\Contract\StandaloneDirectUploadManagerInterface;
use Vortos\ObjectStore\Contract\ImmediateObjectStoreInterface;
use Vortos\ObjectStore\Contract\ImmediateDirectUploadManagerInterface;

ObjectStoreInterface and DirectUploadManagerInterface are the normal business workflow path. Mutations write to the object-store outbox and require the active command transaction.

StandaloneObjectStoreInterface and StandaloneDirectUploadManagerInterface write to the outbox in their own short transaction.

ImmediateObjectStoreInterface and ImmediateDirectUploadManagerInterface call the provider directly with no outbox.

Package Registration

bootstrap/app.php
use Vortos\ObjectStore\DependencyInjection\ObjectStorePackage;

$packages = [
    // ... other packages
    new ObjectStorePackage(),
];

The package is optional. Projects that do not install or register it do not get object-store services, commands, tables, lifecycle tooling, or workers.

On this page