Colorful thumbnail showing two worlds connected by clouds: a beach club party with people taking selfies on the left, and a glowing data center storing media files on the right.

How Topbord Optimized Performance with DigitalOcean Spaces, AWS S3, and CDN Integration

by Evgenii Studitskikh
6 minutes read

At Topbord, we’re redefining social media by blending it with RPG gaming and AI-driven content analysis. If you’re unfamiliar with our journey, check out Building Topbord: Where Social Media Meets RPG Gaming and AI and AI-Powered Content Analysis: The Brain Behind Topbord’s User Experience. As a startup, we needed a robust, scalable, and cost-effective solution for handling user-uploaded media—photos that fuel both social interactions and gameplay events. This led us to implement a Cloud Media Storage system using DigitalOcean Spaces, AWS S3 compatibility, and CDN integration. In this article, we’ll walk you through our approach, provide a step-by-step tutorial, and share Node.js code examples to help you replicate this setup.

Why Cloud Media Storage Matters for Topbord

Topbord isn’t your typical social platform. Every photo upload triggers AI analysis, generates RPG events, and drives user progression. This means our media storage solution had to:

  • Handle high volumes of uploads efficiently.
  • Scale seamlessly as our user base grows.
  • Deliver media quickly to enhance the real-time gaming experience.
  • Integrate with our existing Next.js and Socket.io architecture.

After evaluating options like AWS S3, Google Cloud Storage, and DigitalOcean Spaces, we chose DigitalOcean Spaces for its S3-compatible API, affordability, and built-in CDN capabilities. Here’s how we implemented Cloud Media Storage and why it’s a game-changer for us.

Step-by-Step Tutorial: Implementing Cloud Media Storage

Let’s dive into the technical details of setting up Cloud Media Storage with DigitalOcean Spaces, AWS S3 SDK, and CDN integration. We’ll also show how to upload files using Node.js and store metadata in a MySQL database with TypeORM, plus retrieve files via CDN.

Step 1: Set Up DigitalOcean Spaces

  1. Create a DigitalOcean Account: Sign up at DigitalOcean.
  2. Create a Space: In the DigitalOcean dashboard, navigate to “Spaces,” create a new Space (e.g., topbord-media), and choose a region.
  3. Get API Credentials: Under “API,” generate a Spaces access key and secret. Save these securely.
  4. Enable CDN: In the Space settings, enable the CDN option to get a default endpoint (e.g., https://topbord-media.nyc3.cdn.digitaloceanspaces.com).

Step 2: Configure AWS SDK for DigitalOcean Spaces

DigitalOcean Spaces is S3-compatible, so we use the AWS SDK for Node.js. Install it:

npm install aws-sdk
Bash

Configure the SDK with your Spaces credentials:

const AWS = require('aws-sdk');

// Configure S3 client for DigitalOcean Spaces
const spacesEndpoint = new AWS.Endpoint('nyc3.digitaloceanspaces.com'); // Replace with your region
const s3 = new AWS.S3({
  endpoint: spacesEndpoint,
  accessKeyId: 'YOUR_ACCESS_KEY',
  secretAccessKey: 'YOUR_SECRET_KEY',
});
JavaScript

Step 3: Set Up TypeORM with MySQL

We store media metadata (e.g., file URL, user ID) in a MySQL database using TypeORM. Install dependencies:

npm install typeorm mysql2
Bash

Define a Media entity:

const { Entity, PrimaryGeneratedColumn, Column } = require('typeorm');

@Entity()
class Media {
  @PrimaryGeneratedColumn()
  id;

  @Column()
  userId;

  @Column()
  fileUrl;

  @Column()
  fileName;
}

module.exports = Media;
JavaScript

Configure TypeORM:

const { createConnection } = require('typeorm');

async function initializeDatabase() {
  await createConnection({
    type: 'mysql',
    host: 'localhost',
    port: 3306,
    username: 'your_username',
    password: 'your_password',
    database: 'topbord_db',
    entities: [Media],
    synchronize: true, // Auto-create tables (disable in production)
  });
}

initializeDatabase();
JavaScript

Step 4: Upload a File to DigitalOcean Spaces

Here’s an example of uploading a file (e.g., an image) to Spaces and saving its metadata in the database:

const { Repository } = require('typeorm');
const fs = require('fs');

async function uploadFile(filePath, userId) {
  const fileName = `${Date.now()}-${filePath.split('/').pop()}`;
  const fileContent = fs.readFileSync(filePath);

  // Upload to DigitalOcean Spaces
  const params = {
    Bucket: 'topbord-media',
    Key: fileName,
    Body: fileContent,
    ACL: 'public-read', // Make file publicly accessible
  };

  const { Location } = await s3.upload(params).promise();

  // Save metadata to MySQL
  const mediaRepository = new Repository(Media, (await createConnection()).manager);
  const media = new Media();
  media.userId = userId;
  media.fileUrl = Location; // CDN URL
  media.fileName = fileName;
  await mediaRepository.save(media);

  return media;
}

// Usage example
uploadFile('./uploads/example.jpg', 1)
  .then(media => console.log('Uploaded:', media))
  .catch(err => console.error(err));
JavaScript

This code:

  • Reads the file from the server’s filesystem.
  • Uploads it to the topbord-media Space.
  • Saves the CDN URL and metadata in MySQL.

Step 5: Retrieve a Media File via CDN

To fetch a file’s direct CDN link from the database by ID:

async function getMediaFileUrl(mediaId) {
  const mediaRepository = new Repository(Media, (await createConnection()).manager);
  const media = await mediaRepository.findOne({ id: mediaId });

  if (!media) throw new Error('Media not found');
  return media.fileUrl; // Returns the CDN URL
}

// Usage example
getMediaFileUrl(1)
  .then(url => console.log('CDN URL:', url))
  .catch(err => console.error(err));
JavaScript

The returned URL (e.g., https://topbord-media.nyc3.cdn.digitaloceanspaces.com/1631234567890-example.jpg) is served via DigitalOcean’s CDN for fast delivery.

Why We Chose This Stack

  • DigitalOcean Spaces: Cost-effective ($5/month for 250GB) with S3 compatibility and a built-in CDN.
  • AWS S3 SDK: A mature, widely-supported library that works seamlessly with Spaces.
  • CDN Integration: Reduces latency, critical for real-time features like Socket.io notifications.
  • TypeORM: Simplifies database interactions and scales with our microservices architecture.

For alternatives, AWS S3 offers more advanced features (e.g., lifecycle policies), while Cloudflare R2 promises zero egress fees—something we’re exploring as we grow.

SEO Benefits of Cloud Media Storage

Implementing Cloud Media Storage boosts Topbord’s performance and user experience, which are key for SEO:

  • Faster load times via CDN improve Google PageSpeed scores.
  • Scalable storage ensures uptime as traffic spikes.
  • Efficient media handling supports rich content, driving engagement.

Future Enhancements

We’re planning to:

  • Add image compression before upload (e.g., using sharp).
  • Implement signed URLs for private content.
  • Integrate with Cloudflare for additional caching and security.

Conclusion

Building Cloud Media Storage for Topbord with DigitalOcean Spaces, AWS S3, and CDN integration has been a cornerstone of our platform’s scalability and performance. By combining affordable storage, fast delivery, and a robust database, we’ve created a system that supports our unique blend of social media, gaming, and AI. Try this setup in your next project—it’s a powerful way to manage media at scale!

You may also like