Backing up Badger database from AWS instance storage

I’m using Badger on an AWS i3.xlarge instance as is recommended here: GitHub - dgraph-io/badger: Fast key-value DB in Go.. I need the high IOPS provided by instance storage that I can’t get from EBS volumes so the i3 instances make sense for my use case.

I’m currently trying to solve for recovering data since instance storage is ephemeral. Is anyone else already doing this and can offer a good solution for backing up instance storage and restoring to new instances?

package main

import (
    "fmt"
    "log"
    "os"
    "time"

    "github.com/aws/aws-sdk-go/aws"
    "github.com/aws/aws-sdk-go/aws/session"
    "github.com/aws/aws-sdk-go/service/s3/s3manager"
    "github.com/dgraph-io/badger/v4"
)

func main() {
    // Open the Badger database
    db, err := badger.Open(badger.DefaultOptions("/mnt/badger")) // Adjust path to your instance storage
    if err != nil {
        log.Fatalf("Failed to open Badger DB: %v", err)
    }
    defer db.Close()

    // Create a backup file
    backupFile := fmt.Sprintf("badger-backup-%s.db", time.Now().Format("20060102-150405"))
    f, err := os.Create(backupFile)
    if err != nil {
        log.Fatalf("Failed to create backup file: %v", err)
    }
    defer f.Close()

    // Perform the backup
    _, err = db.Backup(f, 0) // 0 means full backup
    if err != nil {
        log.Fatalf("Failed to backup Badger DB: %v", err)
    }
    log.Printf("Backup completed to %s", backupFile)

    // Upload to S3
    err = uploadToS3(backupFile, "your-s3-bucket-name", backupFile)
    if err != nil {
        log.Fatalf("Failed to upload to S3: %v", err)
    }
    log.Printf("Uploaded %s to S3", backupFile)

    // Optionally, remove the local backup file to save space
    os.Remove(backupFile)
}

// uploadToS3 uploads a file to an S3 bucket
func uploadToS3(filePath, bucket, key string) error {
    sess, err := session.NewSession(&aws.Config{
        Region: aws.String("us-west-2"), // Adjust to your region
    })
    if err != nil {
        return fmt.Errorf("failed to create AWS session: %v", err)
    }

    uploader := s3manager.NewUploader(sess)
    f, err := os.Open(filePath)
    if err != nil {
        return fmt.Errorf("failed to open file: %v", err)
    }
    defer f.Close()

    _, err = uploader.Upload(&s3manager.UploadInput{
        Bucket: aws.String(bucket),
        Key:    aws.String(key),
        Body:   f,
    })
    if err != nil {
        return fmt.Errorf("failed to upload file to S3: %v", err)
    }
    return nil
}