Sua pergunta é curta em detalhes e longa na mão-acenando, mas parece que seu pensamento inicial é um começo muito bom. Seu aplicativo parece bastante semelhante ao Zenoss Monitoring Suite, que usa essencialmente a mesma arquitetura de distribuição de carga para escalar: Vários hosts de monitoramento compartilhando a carga de trabalho de coleta de dados, com uma única interface administrativa e um banco de dados no host admin ou em um separado sistema.
Se o seu gargalo estiver no ponto # 1 (dispositivos enviando dados para o seu servidor), dividir essas tarefas em uma segunda máquina deve criar algum espaço para o crescimento da carga. O maior obstáculo à implementação é geralmente como gerenciar tarefas através de múltiplos servidores Django. O aipo, um mecanismo de fila de tarefas distribuídas, é provavelmente a melhor opção no momento. Ele foi originalmente projetado em torno do Django, o que é bom para você, e tem uma comunidade muito ativa e útil de desenvolvedores e usuários.
Se os pontos 2 e 4 forem sua limitação atual, você provavelmente está falando sobre a escalabilidade do banco de dados. Em geral, trata-se apenas de um problema difícil: não há uma maneira barata, transparente e neutra quanto ao código de ampliar a capacidade do banco de dados.
Se você só precisa obter mais banco de dados para "ler" a capacidade de IO, a replicação provavelmente fará o truque. O Postgres suporta replicação usando uma ferramenta externa chamada Slony-I. A replicação é de um único mestre, com múltiplos hosts "escravo" somente de leitura que recebem cópias de instruções executadas no mestre. Todas as gravações do seu aplicativo (UPDATE, INSERT, DELETE ...) passam pelo host mestre único, mas você distribui suas leituras (SELECT ...) pelo mestre e todos os escravos.
As modificações de código necessárias para leituras distribuídas são geralmente bastante diretas. O Django recentemente adicionou suporte para bancos de dados replicados, os quais eu não usei, mas deve ser muito bom.
Se você precisar de mais capacidade de E / S de gravação de banco de dados, o sharding provavelmente funcionará. Cada host mantém um bloco separado e exclusivo de cada tabela de banco de dados. Os clientes de banco de dados usam uma função determinística para decidir onde qualquer registro deve residir, portanto, a distribuição de carga é efetivamente sem estado e pode ser dimensionada para um grande número de servidores de banco de dados. O novo suporte multi-banco de dados do Django (mesmo link acima) também suporta sharding. Você precisará de algumas alterações no código, a dor deve ser limitada.
Além disso, quero mencionar o Memcached, que parece fazer parte de praticamente todos os aplicativos da Web altamente escalonáveis na Internet hoje (Facebook, Google, Twitter ...). Uma boa implementação de cache pode reduzir seus requisitos de banco de dados a uma fração do seu tamanho original, convertendo pesquisas de banco de dados caras e lentas em pesquisas de cache rápidas e baratas. O Django suporta a integração do Memcached por um bom tempo, agora.
Eu percebo que nada disso é muito específico, mas deve dar a você um ótimo ponto de partida para trabalhar os detalhes. Boa sorte com seu projeto.