Skip to main content

Real architecture · Mid

Canva: 50 million uploads per day

Real production architecture. Key points: blob and video delivery.

15 min read · Source: Canva · Content reviewed on October 23, 2026

Short answer

Real production architecture. Key points: blob and video delivery. According to the engineering team, users upload 50 million new media items per day, and Canva is built with microservices: each service exposes an API, has isolated persistence, and belongs to a small team.

01 · CONTEXT

Canva's media service

According to the engineering team, users upload 50 million new media items per day, and Canva is built with microservices: each service exposes an API, has isolated persistence, and belongs to a small team.

On the access pattern, the media service handles far more reads than writes, most media is rarely modified after it is created, and reads concentrate on recently created media, with the exception of the stock photo and graphics library.

02 · THE MYSQL LIMIT

When the relational database stopped keeping up

For much of Canva's history, most microservices were thin layers over MySQL hosted on AWS RDS. The database was scaled first vertically, with larger instances, and then horizontally, with eventually consistent reads on read replicas in some services.

  1. The typical design of Canva's microservices is a thin layer over MySQL hosted on RDS; the diagram shows this design for the media service.

    Architecture diagram: Media service on MySQL with replicas
    CLCanva user
    CPMedia service
    DBMySQL primary (RDS)
    DBRead replica
  2. For horizontal scaling, some services started reading from MySQL replicas, with eventually consistent reads.

    Architecture diagram: Media service on MySQL with replicas
    CLCanva user
    CPMedia service
    DBMySQL primary (RDS)
    DBRead replicaread replica
  3. Hard limits on MySQL's replication rate imposed a ceiling on the write rate on read replicas.

    Architecture diagram: Media service on MySQL with replicas
    CLCanva user
    CPMedia service
    DBMySQL primary (RDS)
    DBRead replicawrite ceiling

The following table gathers the MySQL limits the team reports.

LimiteWhat the team reports
Schema changeSchema alteration operations on the largest media tables began taking days; even with gh-ost they took up to six weeks, blocking releases.
ReplicationHard limits on MySQL 5.6's replication rate imposed a ceiling on the write rate on read replicas.
Volume EBSThe team was approaching the RDS MySQL EBS volume size limit, 16 TB at the time.
Tail latencyEach increase in the EBS volume brought a small increase in I/O latency, which affected the tail latencies of user requests.
RestartsInstance restarts and version upgrades were not possible without accepting some downtime.
File sizeWith the ext3 file system, MySQL table files were limited to 2 TB.

03 · BUYING TIME

Extending MySQL and choosing the destination

In mid-2017, with the number of media items approaching 1 billion and growing exponentially, the team began investigating migration paths, with a strong preference for incremental approaches.

To extend MySQL's life, the team moved the content metadata, the most modified part of the schema, to a JSON column, denormalized some tables to reduce lock contention and joins, and removed foreign key constraints.

Near the end of the MySQL solution's life, the team implemented a simple sharding scheme, to avoid the ext3 table file size limit and the replication throughput ceiling.

  1. The solution was optimized for the most common request, lookup by ID used when loading designs.

    Architecture diagram: MySQL with application-level sharding
    CPMedia service
    DBFragmento A
    DBFragmento B
  2. Less common requests, such as listing all of a user's media, required inefficient scatter-gather queries.

    Architecture diagram: MySQL with application-level sharding
    CPMedia service
    DBFragmento Aqueried on listing
    DBFragmento Bqueried on listing

In parallel, the team investigated and prototyped long-term solutions. With a short deadline, a preference for a managed solution, prior experience with simpler DynamoDB services, and a prototype, it chose DynamoDB as the provisional target. It also needed a migration strategy with no impact on users and a cutover with no downtime.

04 · LIVE MIGRATION

Copying the history without stopping the product

The team considered writing to both databases on every create or update, building and replaying an ordered log of all changes, among other options. The chosen approach would give full control over the data mapping, allow migrating progressively, live, and take load off the MySQL cluster as early as possible.

The design uses message queues that only identify the media item, instead of carrying the update content. The diagram shows the flow in six steps.

  1. The current state of each media item is read from the MySQL primary by a worker at the time of copying it.

    Architecture diagram: Live migration from MySQL to DynamoDB
    CPMedia service
    DBMySQL primary
    QHigh-priority queue
    QLow-priority queue
    CPReplication worker
    CPScan process
    DBDynamoDB
  2. Queued messages only identify which media item was created, updated, or read, without the update content.

    Architecture diagram: Live migration from MySQL to DynamoDB
    CPMedia service
    DBMySQL primary
    QHigh-priority queuehigh priority
    QLow-priority queuelow priority
    CPReplication worker
    CPScan process
    DBDynamoDB
  3. A worker processes each message, reads the current state from the MySQL primary, and updates DynamoDB if necessary, which allowed messages to be reordered or repeated arbitrarily.

    Architecture diagram: Live migration from MySQL to DynamoDB
    CPMedia service
    DBMySQL primary
    QHigh-priority queue
    QLow-priority queue
    CPReplication worker
    CPScan process
    DBDynamoDBnew storage
  4. Creates and updates go to the high-priority queue and reads to the low-priority one; workers only read from the low-priority queue after draining the high-priority one.

    Architecture diagram: Live migration from MySQL to DynamoDB
    CPMedia service
    DBMySQL primary
    QHigh-priority queue
    QLow-priority queue
    CPReplication worker
    CPScan process
    DBDynamoDB
  5. A scan process walks through all media, starting with the most recently created, and with backpressure only advances while the low-priority queue is approximately empty.

    Architecture diagram: Live migration from MySQL to DynamoDB
    CPMedia service
    DBMySQL primary
    QHigh-priority queue
    QLow-priority queue
    CPReplication worker
    CPScan process
    DBDynamoDB
  6. Eventually consistent reads of individual media items are now served from DynamoDB, with fallback to MySQL for the few media items not yet replicated.

    Architecture diagram: Live migration from MySQL to DynamoDB
    CPMedia service
    DBMySQL primary
    QHigh-priority queue
    QLow-priority queue
    CPReplication worker
    CPScan process
    DBDynamoDB

The team implemented a dual-read process with comparison to test replication. Requests that do not identify the media by ID, such as finding all of a user's media, could only be served after all media had been replicated.

05 · CUTOVER

The riskiest part: switching the writes

Switching all writes to DynamoDB was the riskiest part of the process. The new code used transactional and conditional writes to guarantee the same contracts as the previous implementation.

To reduce risk, the team wrote a cutover runbook, using the flag system to be able to switch reads back to MySQL in seconds, and rehearsed it as the change moved through the development and staging environments. The production cutover went smoothly, with no downtime or errors.

06 · RESULT AND TRADE-OFFS

What was gained and what was lost

Canva's monthly active users have more than tripled since the migration. According to the team, DynamoDB has been very stable, with autoscaling as Canva grows, and costs less than the AWS RDS clusters it replaced.

Loss or costReported situation
Schema changes and backfillsNow require rigorously writing and testing migration code with parallel scan.
Ad hoc SQL queriesThe team lost the ability to run ad hoc SQL on a MySQL replica and today meets that need with CDC to the data warehouse.
Composite global secondary indexesThey are needed for the existing access patterns and are still created manually, by concatenating attributes.

Looking back, the team says that, facing the same problem today, it would strongly consider mature hosted NewSQL products again. The media service today stores more than 25 billion user-uploaded media items, with another 50 million per day.

Frequently asked questions

What is Canva: 50 million uploads per day?

Real production architecture. Key points: blob and video delivery.

What does the Canva: 50 million uploads per day design cover?

It is organized in these sections: Canva's media service, When the relational database stopped keeping up, Extending MySQL and choosing the destination, Copying the history without stopping the product, The riskiest part: switching the writes, and What was gained and what was lost.

How long is Canva: 50 million uploads per day and what level is it?

It takes about 15 minutes to read and is rated Mid level.

Now design it yourself

Run this case as an interview in the System Design school: you make the decisions, the tutor challenges them and you see how your design scores.