MySQL 5.6 @ AWS RDS read IOPS plateaus lower than write IOPS
Reads are cached.  If your data is smaller than the buffer_pool, everything will be read once, then read IOPs will drop to virtually zero.

There are many writes -- write the data, update the index, the double-buffer, the undo log, the binlog, etc.  Still, there is some caching going on there.  See the "change buffer".

So, I am surprised that the Read IOPs are so high.  And I can't explain its flatness.  Please describe what your app does and how big the data is.

UUIDs

So, the problem stems from having the PRIMARY KEY(id) being a 'random' value, while doing reads in somewhat chronological order, or by station_id.

First, let's try to get rid of id.  Is there another combination of columns that is unique?  If so, it might be a better PK.

Probably, this is the best PK:

PRIMARY KEY(station_id, created_at  -- in this order
            , id   -- include only if needed for uniqueness
           ),
INDEX(created_at) -- for finding today's set of rows for analytics?


I assume there are only hundreds, maybe a few thousand 'stations'?

With PK(id), each INSERT is hitting a random spot in the table.  Given that the buffer_pool is only 10% of the size of the table, this means that 90% of the time there will be a cache miss.  Ditto for SELECTing.

With PK(station_id, created_at), there will be hundreds, maybe thousands of "hot spots", so the INSERTs will be more easily cached.  And even the reads, which need INDEX(created_at) will bounce around only those few spots, not bounce around the entire table.

If a block (16KB in InnoDB) contains 100 rows (a convenient Rule of Thumb), then the inserts and selects discussed so far will be inherently 90 times as fast as before.  (OK, it might be only 5-10 times as fast, but that is still  very good, correct?)

(I discuss the UUID problem here, but the cure in it depends on Type 1; you are using Type 4.  Instead, we cna take advantage of created_at.)

Another issue... I see several long strings in that table.  Do those columns contain the same strings over and over?  If so, you should seriously consider normalizing them.  Then you could replace VARCHARs with, say, 2-byte SMALLINT UNSIGNED (for up to 65K distinct values).  Shrinking the table will help performance, especially when it is bigger than the buffer_pool.

I see several redundant indexes; drop the extras.

INDEX(a), INDEX(a)  -- drop one of them
INDEX(a), INDEX(a,b)  -- drop (a), since the other one can handle its needs


Use NOT NULL when appropriate.

INT takes 4 bytes; use smaller numeric types where appropriate.