|
| 1 | +# Title: Switch to Tigris for Image Storage |
| 2 | + |
| 3 | +Date: 2025-02-20 |
| 4 | + |
| 5 | +Status: accepted |
| 6 | + |
| 7 | +## Context |
| 8 | + |
| 9 | +The Epic Stack previously stored uploaded images directly in SQLite using binary |
| 10 | +data storage. While this approach is simple and works well for small |
| 11 | +applications, it has several limitations (as noted in the previous decision |
| 12 | +[018-images.md](docs/decisions/018-images.md)): |
| 13 | + |
| 14 | +1. Binary data in SQLite increases database size and backup complexity |
| 15 | +2. Large binary data in SQLite can impact database performance |
| 16 | +3. SQLite backups become larger and more time-consuming when including binary |
| 17 | + data |
| 18 | +4. No built-in CDN capabilities for serving images efficiently |
| 19 | + |
| 20 | +## Decision |
| 21 | + |
| 22 | +We will switch from storing images in SQLite to storing them in Tigris, an |
| 23 | +S3-compatible object storage service. This change will: |
| 24 | + |
| 25 | +1. Move binary image data out of SQLite into specialized object storage |
| 26 | +2. Maintain metadata about images in SQLite (references, ownership, etc.) |
| 27 | +3. Leverage Tigris's S3-compatible API for efficient image storage and retrieval |
| 28 | +4. Enable better scalability for applications with many image uploads |
| 29 | + |
| 30 | +To keep things lightweight, we will not be using an S3 SDK to integrate with |
| 31 | +Tigris and instead we'll manage authenticated fetch requests ourselves. |
| 32 | + |
| 33 | +## Consequences |
| 34 | + |
| 35 | +### Positive |
| 36 | + |
| 37 | +1. Reduced SQLite database size and improved backup efficiency |
| 38 | +2. Better separation of concerns (binary data vs relational data) |
| 39 | +3. Potentially better image serving performance through Tigris's infrastructure |
| 40 | +4. More scalable solution for applications with heavy image usage |
| 41 | +5. Easier to implement CDN capabilities in the future |
| 42 | +6. Simplified database maintenance and backup procedures |
| 43 | +7. Tigris storage is much cheaper than Fly volume storage |
| 44 | + |
| 45 | +### Negative |
| 46 | + |
| 47 | +1. Additional external service dependency (though Fly as built-in support and no |
| 48 | + additional account needs to be created) |
| 49 | +2. Need to manage Tigris configuration |
| 50 | +3. Slightly more complex deployment setup |
| 51 | +4. Additional complexity in image upload and retrieval logic |
| 52 | + |
| 53 | +## Implementation Notes |
| 54 | + |
| 55 | +The implementation involves: |
| 56 | + |
| 57 | +1. Setting up Tigris configuration |
| 58 | +2. Modifying image upload handlers to store files in Tigris |
| 59 | +3. Updating image retrieval routes to serve from Tigris |
| 60 | +4. Maintaining backward compatibility during migration (database migration is |
| 61 | + required as well as manual migration of existing images) |
| 62 | +5. Providing migration utilities for existing applications |
| 63 | + |
| 64 | +## References |
| 65 | + |
| 66 | +- [Tigris Documentation](https://www.tigris.com/docs) |
| 67 | +- Previous image handling: [018-images.md](docs/decisions/018-images.md) |
0 commit comments