1,215 karma · joined May 19, 2008
Twitter: @obeattie
At Monzo we aim to build the best current account in the world. We are always keen to hear from capable, creative engineers who want to help us accomplish that goal; specifically backend engineers and Android engineers, and we also offer paid engineering internships.
Our engineering team have a variety of different backgrounds: we have several non-graduates; only a couple of us studied Computer Science; one of the team has a degree in Marketing; some of us have worked in huge companies; some have only ever worked in startups; others are former consultants. As long as you enjoy learning new things, we’d love to talk to you.
If you’re unsure about applying or have any questions about the role or team, please don’t hesitate to email me (oliver@monzo.com) directly :) We're very open about what we do in general, so our blog is a good place to learn more about what we do: https://monzo.com/blog/
We may unify the two at some point, but there's no immediate need to do so. While the write use-case is quite similar across both, the read use-case is quite different: slog requires reasonably low latency reads soon after the data is written, data can age out after 2-30 days depending on severity, and sometimes dropping events is acceptable. It would be acceptable for reads from the "archival" system to take minutes or even hours, the data should be kept forever (or for a long time), and dropping events is never acceptable.
A lot of the feedback from my blog post a month or so ago was that the "why" was not clear enough, so I guess I focussed more on this. Now I've (hopefully!) covered that better, I agree that more depth on these topics would be helpful.
I just want to say that I think there is a huge amount of FUD about how you can and cannot build your technology as a regulated entity – and in particular as a bank. In reality, close to 100% of requirements from a regulator will tell you _what_ you must build, not _how_ you must build it. Even then, especially in terms of resilience and security, they are almost always a subset of our own requirements.
What can be more of a challenge is convincing an auditor that what you have done is acceptable, since it can be so different from what they may have seen before. Again, I don't think this is a reason to compromise. We see technology as a major competitive advantage, so it is worth the effort to find open-minded auditors, and spend time to explain and demonstrate how (and why) our software meets the requirements.
I don't think there's any way we could build a secure, resilient bank with the kind of product experience we want, AND do it on the budget of a startup if we approach technology through the same lens as existing banks.
* Every request that comes into our system is assigned a unique ID, which is propagated on every downstream call and returned in a response header. When logs are emitted during request processing, they are tagged with this ID. A system we've built in-house indexes these log events against their trace ID in Cassandra (on a separate cluster). This lets us take a failing, slow, or otherwise interesting request and look up all the things that happened to it during processing. Events in this system are TTL'd according to their severity – so an event at critical or error severity is kept longer than one at debug severity. * stdout/stderr from all our containers is forwarded to journald on each host. Logstash then pushes all these logs to Elastic (and also to permanent cold storage). This is useful to look at the "big picture" and means we can analyse all the logs in aggregate and makes it very obvious when something is _very_ wrong and causing a lot of requests to fail, but is less useful than slog for pinpointing a specific issue.
It's worth also noting (since I find often a whole load of things can be mixed into logging) that we do not drive our monitoring off these logs, at least at the moment. We have separate systems for that.
And as an aside, I'll also be giving a longer talk at Kubecon going into more detail on some of this stuff :-)
For example, we chose HTTP as our RPC protocol because it is widely supported in many languages, and has mature support in Finagle. HTTP/2 fixes most of the performance issues with HTTP, and we have options (eg. to use mux) if we still find there are performance problems – although at the moment, we are quite happy with performance.
At Monzo we aim to build the best current account in the world. We are always keen to hear from capable, creative engineers who want to help us accomplish that goal.
We’re still a relatively small company with only 10 people in the backend engineering team and 50 people in total. This means you will need to wear many hats in the beginning but it also means there are many interesting challenges ahead that you can specialise in if you like. Broadly, the work we’re doing covers these areas:
* Distributed platform: We aim to be the first bank without a single point of failure
* Banking and payments: We write code that moves money
* Product engineering: We help our customers by hiding the boring parts of money management
* Financial crime: We need to stay ahead of criminals trying to steal data and money
* Internal tooling: We automate everything so the rest of the team can work smarter
Our backend architecture is composed of hundreds of distributed Go microservices running in the cloud. They are managed by Kubernetes, store data in Cassandra, do RPC with linkerd/Finagle, and use Kafka for asynchronous queueing.
Lots more detail is on our website : https://boards.greenhouse.io/mondo/jobs/244898
We'll almost certainly add additional required factors to this process (eg. biometrics), as we see the user logging into the Mondo app on a new device as one of the most critical from a security perspective.
While a malicious application can inject JavaScript to intercept the username, this alone is useless to an attacker.
I agree in the "native app on same device" situation, we can bypass all this by bouncing straight to our app though.
1. MyLittleApp opens web view to log into Mondo
2. User enters something to identify themselves into the web view (eg. email address, phone number)
3. We dispatch a notification to the user's registered device (ie. the Mondo app where the user is logged in – this may be the same device or a different device)
4. User opens the Mondo app and accepts/rejects the authorisation request
5. User returns to MyLittleApp, OAuth flow completes
In this flow, the user is not exposing their login credentials to the app… at worst, the app could extract their email/phone number. It also introduces another factor into the auth flow: the user's registered device.