This sounds like a very odd use case. Are you sure you're not looking for a more all-encompassing solution than you actually need? There are several approaches you could apply to a map to make it possible to have it be expansive and yet still small:
Sparse data structures E.g. if your world is mostly grass that the player has to traverse, with a few "islands" or terrain actually modified by a player, you can save only the parts the player actually modified, and whenever the game is asked to show an area that isn't in your save game, you just return a default tile (in our example, grass).
Palettes Many maps contain repeating patterns. E.g. long stretches that are only grass, or maybe a building's roof is always made up of two start tiles, an arbitrary number of pairs of middle tiles, and then two end tiles. When you transfer it, instead of sending these tiles individually, what you can instead do is just have a "palette" stored locally that contains the two start tiles in the right arrangement, a pair of middle tiles, and the two end tiles, each given a number, and transmit 3 special codes that say "palette entry 1", "palette entry 2", "palette entry 3".
Run-Length Encoding Often maps also contain long stretches of identical information. A common mechanism to reduce that is to just send a number with every tile. So instead of "roof start", "roof middle", "roof middle", "roof middle", "roof end", you transfer 1x "roof start", 3x "roof middle", 1x "roof end". Now while maps that have few repeating items may use more room to represent this information, repetitive maps collapse so much that they'll usually balance things out again.
Repeat codes Similarly, you can add a buffer in which you remember the last row (or whatever unit you choose) you received, and then add a simple "repeat last row" code. So if you have a stretch that is all the same tile, you transfer one row of that tile, and then 10 short codes saying "again". There are even more complex ways to do this.
E.g. HyperCard had a B/W graphic format where they even XORed together the previous row with another one. That way, they were able to re-transmit only the different parts of a row, and generate three repeating patterns out of two repeats interrupted by a different one.
E.g. a checkerboard pattern is every other pixel is black, but among three rows, every other row is the reverse. If you then just say "512x black XORed onto the previous white/black row", you get black/white row instead. with much less information. Basically, a checkerboard turns from uncompressable into one row of black/white pixels followed by a bunch of "repeat inverted" codes.
Selective Updates By remembering the size and position (in tile coordinates) of a block of tiles, you can re-transmit arbitrary subsections of a map. If a single tile changes, you only transmit that one tile's new value and tell your app "insert that at position 100,100. Or insert this 4x3 block of tiles at position 17,2 (effectively overwriting the tiles from 17,2 to 21,2 and 17,3 to 21,3 and 17,4 to 21,4).
Information Reduction This is like Mipmapping in computer games: If you know your player will be zoomed out very far, try to transmit less information first that looks the same. E.g. if a user is zoomed at 1/4th, you could transmit only 1/4th of the tiles. If there are squares of the same tiles, just transmit the one larger tile. And then only transmit more detailed information for areas that contain more information, or even that you know the user is working with.
This could e.g. mean that you show certain houses slightly wrong in the zoomed-out version, and as you zoom in make them look more right. What you can do here depends heavily on the tiles you have and what is important in your game.
Only when the user actually clicks a certain tile in a huge, zoomed-out map, you could then load the information you need to let them manipulate those tiles in detail, and render it with more precision, scaled down. And you could of course do like progressive loading of images in older browsers used to work, where you first get the low-res version of the map, and then slowly you load more detail. The low-res version lets the user orient themselves and move the mouse to where they want to manipulate, and by that time the high-res version may have been loaded in the background.
Generation Numbers Whenever something on the map is changed, you increment a "generation" counter you have, and you remember that number on each tile when you change it. It is like a "last changed" timestamp on a file, just that we don't use wall time, because we don't really care about the seconds it took to make the actual change on our server, or the time that goes by while the user is logged out. Now, when your user logs into the server, they can tell you "this is the last time stamp I've seen" and you can just collect all tiles that have a bigger generation number than that and send them back.
You're not really saying much about your game and how it'll actually work, and why maps can be this large that transferring this data would be a problem.